1 /* #define OLD_ASTERISK */
4 * Asterisk -- An open source telephony toolkit.
6 * Copyright (C) 2002-2007, 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.73 09/04/07
26 * \author Jim Dixon, WB6NIL <jim@lambdatel.com>
28 * \note Serious contributions by Steve RoDgers, WA6ZFT <hwstar@rodgers.sdcoxmail.com>
30 * See http://www.zapatatelephony.org/app_rpt.html
33 * Repeater / Remote Functions:
34 * "Simple" Mode: * - autopatch access, # - autopatch hangup
36 * See the function list in rpt.conf (autopatchup, autopatchdn)
37 * autopatchup can optionally take comma delimited setting=value pairs:
40 * context=string : Override default context with "string"
41 * dialtime=ms : Specify the max number of milliseconds between phone number digits (1000 milliseconds = 1 second)
42 * farenddisconnect=1 : Automatically disconnect when called party hangs up
43 * noct=1 : Don't send repeater courtesy tone during autopatch calls
44 * quiet=1 : Don't send dial tone, or connect messages. Do not send patch down message when called party hangs up
47 * Example: 123=autopatchup,dialtime=20000,noct=1,farenddisconnect=1
49 * To send an asterisk (*) while dialing or talking on phone,
50 * use the autopatch acess code.
56 * 2 - Give Time of Day
57 * 3 - Give software Version
59 * cop (control operator) cmds:
61 * 1 - System warm boot
64 * 4 - Test Tone On/Off
65 * 5 - Dump System Variables on Console (debug)
66 * 6 - PTT (phone mode only)
67 * 7 - Time out timer enable
68 * 8 - Time out timer disable
69 * 9 - Autopatch enable
70 * 10 - Autopatch disable
73 * 13 - Query System State
74 * 14 - Change System State
75 * 15 - Scheduler Enable
76 * 16 - Scheduler Disable
77 * 17 - User functions (time, id, etc) enable
78 * 18 - User functions (time, id, etc) disable
79 * 19 - Select alternate hang timer
80 * 20 - Select standard hang timer
84 * 1 - Disconnect specified link
85 * 2 - Connect specified link -- monitor only
86 * 3 - Connect specified link -- tranceive
87 * 4 - Enter command mode on specified link
89 * 6 - Disconnect all links
90 * 11 - Disconnect a previously permanently connected link
91 * 12 - Permanently connect specified link -- monitor only
92 * 13 - Permanently connect specified link -- tranceive
93 * 15 - Full system status (all nodes)
94 * 16 - Reconnect links disconnected with "disconnect all links"
95 * 200 thru 215 - (Send DTMF 0-9,*,#,A-D) (200=0, 201=1, 210=*, etc)
99 * 1 - Recall Memory MM (*000-*099) (Gets memory from rpt.conf)
100 * 2 - Set VFO MMMMM*KKK*O (Mhz digits, Khz digits, Offset)
101 * 3 - Set Rx PL Tone HHH*D*
102 * 4 - Set Tx PL Tone HHH*D* (Not currently implemented with DHE RBI-1)
103 * 5 - Link Status (long)
104 * 6 - Set operating mode M (FM, USB, LSB, AM, etc)
105 * 100 - RX PL off (Default)
107 * 102 - TX PL Off (Default)
112 * 107 - Bump Down 20 Hz
113 * 108 - Bump Down 100 Hz
114 * 109 - Bump Down 500 Hz
115 * 110 - Bump Up 20 Hz
116 * 111 - Bump Up 100 Hz
117 * 112 - Bump Up 500 Hz
118 * 113 - Scan Down Slow
119 * 114 - Scan Down Medium
120 * 115 - Scan Down Fast
122 * 117 - Scan Up Medium
124 * 119 - Transmit allowing auto-tune
125 * 140 - Link Status (brief)
126 * 200 thru 215 - (Send DTMF 0-9,*,#,A-D) (200=0, 201=1, 210=*, etc)
129 * 'duplex' modes: (defaults to duplex=2)
131 * 0 - Only remote links key Tx and no main repeat audio.
132 * 1 - Everything other then main Rx keys Tx, no main repeat audio.
134 * 3 - Normal except no main repeat audio.
135 * 4 - Normal except no main repeat audio during autopatch only
140 <depend>zaptel</depend>
141 <depend>tonezone</depend>
142 <defaultenabled>no</defaultenabled>
145 /* Un-comment the following to include support for MDC-1200 digital tone
146 signalling protocol (using KA6SQG's GPL'ed implementation) */
147 /* #include "mdc_decode.c" */
149 /* Un-comment the following to include support for notch filters in the
150 rx audio stream (using Tony Fisher's mknotch (mkfilter) implementation) */
151 /* #include "rpt_notch.c" */
153 /* maximum digits in DTMF buffer, and seconds after * for DTMF command timeout */
156 #define MAXMACRO 2048
157 #define MAXLINKLIST 512
158 #define LINKLISTTIME 10000
159 #define LINKLISTSHORTTIME 200
160 #define MACROTIME 100
161 #define MACROPTIME 500
162 #define DTMF_TIMEOUT 3
163 #define KENWOOD_RETRIES 5
165 #define AUTHTELLTIME 7000
166 #define AUTHTXTIME 1000
167 #define AUTHLOGOUTTIME 25000
170 #define MAXFILTERS 10
173 #define DISC_TIME 10000 /* report disc after 10 seconds of no connect */
174 #define MAX_RETRIES 5
175 #define MAX_RETRIES_PERM 1000000000
177 #define REDUNDANT_TX_TIME 2000
179 #define RETRY_TIMER_MS 5000
181 #define START_DELAY 2
183 #define MAXPEERSTR 31
189 #define MONITOR_DISK_BLOCKS_PER_MINUTE 38
191 #define DEFAULT_MONITOR_MIN_DISK_BLOCKS 10000
192 #define DEFAULT_REMOTE_INACT_TIMEOUT (15 * 60)
193 #define DEFAULT_REMOTE_TIMEOUT (60 * 60)
194 #define DEFAULT_REMOTE_TIMEOUT_WARNING (3 * 60)
195 #define DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ 30
197 #define NODES "nodes"
198 #define EXTNODES "extnodes"
199 #define MEMORY "memory"
200 #define MACRO "macro"
201 #define FUNCTIONS "functions"
202 #define TELEMETRY "telemetry"
203 #define MORSE "morse"
206 #define EXTNODEFILE "/var/lib/asterisk/rpt_extnodes"
208 #define DEFAULT_IOBASE 0x378
210 #define DEFAULT_CIV_ADDR 0x58
212 #define MAXCONNECTTIME 5000
214 #define MAXNODESTR 300
216 #define MAXPATCHCONTEXT 100
218 #define ACTIONSIZE 32
220 #define TELEPARAMSIZE 256
222 #define REM_SCANTIME 100
224 #define DTMF_LOCAL_TIME 250
225 #define DTMF_LOCAL_STARTTIME 500
227 #define IC706_PL_MEMORY_OFFSET 50
229 #define ALLOW_LOCAL_CHANNELS
231 enum {REM_OFF
,REM_MONITOR
,REM_TX
};
233 enum{ID
,PROC
,TERM
,COMPLETE
,UNKEY
,REMDISC
,REMALREADY
,REMNOTFOUND
,REMGO
,
234 CONNECTED
,CONNFAIL
,STATUS
,TIMEOUT
,ID1
, STATS_TIME
,
235 STATS_VERSION
, IDTALKOVER
, ARB_ALPHA
, TEST_TONE
, REV_PATCH
,
236 TAILMSG
, MACRO_NOTFOUND
, MACRO_BUSY
, LASTNODEKEY
, FULLSTATUS
,
237 MEMNOTFOUND
, INVFREQ
, REMMODE
, REMLOGIN
, REMXXX
, REMSHORTSTATUS
,
238 REMLONGSTATUS
, LOGINREQ
, SCAN
, SCANSTAT
, TUNE
, SETREMOTE
,
239 TIMEOUT_WARNING
, ACT_TIMEOUT_WARNING
, LINKUNKEY
, UNAUTHTX
};
242 enum {REM_SIMPLEX
,REM_MINUS
,REM_PLUS
};
244 enum {REM_LOWPWR
,REM_MEDPWR
,REM_HIPWR
};
246 enum {DC_INDETERMINATE
, DC_REQ_FLUSH
, DC_ERROR
, DC_COMPLETE
, DC_COMPLETEQUIET
, DC_DOKEY
};
248 enum {SOURCE_RPT
, SOURCE_LNK
, SOURCE_RMT
, SOURCE_PHONE
, SOURCE_DPHONE
};
250 enum {DLY_TELEM
, DLY_ID
, DLY_UNKEY
, DLY_CALLTERM
, DLY_COMP
, DLY_LINKUNKEY
};
252 enum {REM_MODE_FM
,REM_MODE_USB
,REM_MODE_LSB
,REM_MODE_AM
};
254 enum {HF_SCAN_OFF
,HF_SCAN_DOWN_SLOW
,HF_SCAN_DOWN_QUICK
,
255 HF_SCAN_DOWN_FAST
,HF_SCAN_UP_SLOW
,HF_SCAN_UP_QUICK
,HF_SCAN_UP_FAST
};
257 #include "asterisk.h"
259 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
267 #include <sys/types.h>
268 #include <sys/stat.h>
272 #include <sys/stat.h>
273 #include <sys/time.h>
274 #include <sys/file.h>
275 #include <sys/ioctl.h>
280 #include <linux/zaptel.h>
281 #include <tonezone.h>
283 #include <zaptel/zaptel.h>
284 #include <zaptel/tonezone.h>
286 #include <netinet/in.h>
287 #include <arpa/inet.h>
289 #include "asterisk/utils.h"
290 #include "asterisk/lock.h"
291 #include "asterisk/file.h"
292 #include "asterisk/logger.h"
293 #include "asterisk/channel.h"
294 #include "asterisk/callerid.h"
295 #include "asterisk/pbx.h"
296 #include "asterisk/module.h"
297 #include "asterisk/translate.h"
298 #include "asterisk/features.h"
299 #include "asterisk/options.h"
300 #include "asterisk/cli.h"
301 #include "asterisk/config.h"
302 #include "asterisk/say.h"
303 #include "asterisk/localtime.h"
304 #include "asterisk/cdr.h"
305 #include "asterisk/options.h"
308 /* Start a tone-list going */
309 int ast_playtones_start(struct ast_channel
*chan
, int vol
, const char* tonelist
, int interruptible
);
310 /*! Stop the tones from playing */
311 void ast_playtones_stop(struct ast_channel
*chan
);
313 static char *tdesc
= "Radio Repeater / Remote Base version 0.73 09/04/2007";
315 static char *app
= "Rpt";
317 static char *synopsis
= "Radio Repeater/Remote Base Control System";
319 static char *descrip
=
320 " Rpt(nodename[|options]): Radio Remote Link or Remote Base Link Endpoint Process.\n"
322 " Not specifying an option puts it in normal endpoint mode (where source\n"
323 " IP and nodename are verified).\n"
325 " Options are as follows:\n"
327 " X - Normal endpoint mode WITHOUT security check. Only specify\n"
328 " this if you have checked security already (like with an IAX2\n"
329 " user/password or something).\n"
331 " Rannounce-string[|timeout[|timeout-destination]] - Amateur Radio\n"
332 " Reverse Autopatch. Caller is put on hold, and announcement (as\n"
333 " specified by the 'announce-string') is played on radio system.\n"
334 " Users of radio system can access autopatch, dial specified\n"
335 " code, and pick up call. Announce-string is list of names of\n"
336 " recordings, or \"PARKED\" to substitute code for un-parking,\n"
337 " or \"NODE\" to substitute node number.\n"
339 " P - Phone Control mode. This allows a regular phone user to have\n"
340 " full control and audio access to the radio system. For the\n"
341 " user to have DTMF control, the 'phone_functions' parameter\n"
342 " must be specified for the node in 'rpt.conf'. An additional\n"
343 " function (cop,6) must be listed so that PTT control is available.\n"
345 " D - Dumb Phone Control mode. This allows a regular phone user to\n"
346 " have full control and audio access to the radio system. In this\n"
347 " mode, the PTT is activated for the entire length of the call.\n"
348 " For the user to have DTMF control (not generally recomended in\n"
349 " this mode), the 'dphone_functions' parameter must be specified\n"
350 " for the node in 'rpt.conf'. Otherwise no DTMF control will be\n"
351 " available to the phone user.\n"
354 static int debug
= 0; /* Set this >0 for extra debug output */
355 static int nrpts
= 0;
357 static char remdtmfstr
[] = "0123456789*#ABCD";
359 enum {TOP_TOP
,TOP_WON
,WON_BEFREAD
,BEFREAD_AFTERREAD
};
361 int max_chan_stat
[] = {22000,1000,22000,100,22000,2000,22000};
370 unsigned long largest
;
371 struct timeval largest_time
;
374 char *discstr
= "!!DISCONNECT!!";
375 static char *remote_rig_ft897
="ft897";
376 static char *remote_rig_rbi
="rbi";
377 static char *remote_rig_kenwood
="kenwood";
378 static char *remote_rig_ic706
="ic706";
386 #define HANGTIME 5000
387 #define TOTIME 180000
388 #define IDTIME 300000
390 #define MAX_STAT_LINKS 32
391 #define POLITEID 30000
392 #define FUNCTDELAY 1500
395 #define MAXXLATTIME 3
397 #define MAX_SYSSTATES 10
401 char funccharseq
[MAXXLAT
];
402 char endcharseq
[MAXXLAT
];
403 char passchars
[MAXXLAT
];
409 static time_t starttime
= 0;
411 static pthread_t rpt_master_thread
;
417 struct rpt_link
*next
;
418 struct rpt_link
*prev
;
419 char mode
; /* 1 if in tx mode */
422 char name
[MAXNODESTR
]; /* identifier (routing) string */
441 long long connecttime
;
442 struct ast_channel
*chan
;
443 struct ast_channel
*pchan
;
444 char linklist
[MAXLINKLIST
];
445 time_t linklistreceived
;
448 int linkunkeytocttimer
;
449 struct ast_frame
*lastf1
,*lastf2
;
450 struct rpt_chan_stat chan_stat
[NRPTSTAT
];
455 struct rpt_lstat
*next
;
456 struct rpt_lstat
*prev
;
457 char peer
[MAXPEERSTR
];
458 char name
[MAXNODESTR
];
463 long long connecttime
;
464 struct rpt_chan_stat chan_stat
[NRPTSTAT
];
469 struct rpt_tele
*next
;
470 struct rpt_tele
*prev
;
472 struct ast_channel
*chan
;
474 struct rpt_link mylink
;
475 char param
[TELEPARAMSIZE
];
480 struct function_table_tag
482 char action
[ACTIONSIZE
];
483 int (*function
)(struct rpt
*myrpt
, char *param
, char *digitbuf
,
484 int command_source
, struct rpt_link
*mylink
);
487 /* Used to store the morse code patterns */
495 struct telem_defaults
507 char autopatchdisable
;
508 char schedulerdisable
;
517 struct ast_config
*cfg
;
524 struct rpt_chan_stat chan_stat
[NRPTSTAT
];
535 char *link_functions
;
536 char *phone_functions
;
537 char *dphone_functions
;
546 int tailsquashedtime
;
549 char *tailmessages
[500];
561 char propagate_phonedtmf
;
563 unsigned char civaddr
;
564 struct rpt_xlat inxlat
;
565 struct rpt_xlat outxlat
;
569 char *skedstanzaname
;
570 char *txlimitsstanzaname
;
572 int remoteinacttimeout
;
574 int remotetimeoutwarning
;
575 int remotetimeoutwarningfreq
;
577 struct sysstate s
[MAX_SYSSTATES
];
579 struct rpt_link links
;
590 char dtmfbuf
[MAXDTMF
];
591 char macrobuf
[MAXMACRO
];
592 char rem_dtmfbuf
[MAXDTMF
];
593 char lastdtmfcommand
[MAXDTMF
];
595 struct ast_channel
*rxchannel
,*txchannel
, *monchannel
;
596 struct ast_channel
*pchannel
,*txpchannel
, *zaprxchannel
, *zaptxchannel
;
597 struct ast_frame
*lastf1
,*lastf2
;
598 struct rpt_tele tele
;
599 struct timeval lasttv
,curtv
;
600 pthread_t rpt_call_thread
,rpt_thread
;
601 time_t dtmf_time
,rem_dtmf_time
,dtmf_time_rem
;
602 int tailtimer
,totimer
,idtimer
,txconf
,conf
,callmode
,cidx
,scantimer
,tmsgtimer
,skedtimer
;
606 int dtmfidx
,rem_dtmfidx
;
607 int dailytxtime
,dailykerchunks
,totalkerchunks
,dailykeyups
,totalkeyups
,timeouts
;
608 int totalexecdcommands
, dailyexecdcommands
;
611 long long totaltxtime
;
613 char exten
[AST_MAX_EXTENSION
];
614 char freq
[MAXREMSTR
],rxpl
[MAXREMSTR
],txpl
[MAXREMSTR
];
624 char lastlinknode
[MAXNODESTR
];
625 char savednodes
[MAXNODESTR
];
627 char patchfarenddisconnect
;
630 char patchcontext
[MAXPATCHCONTEXT
];
633 int phone_longestfunc
;
634 int dphone_longestfunc
;
635 int link_longestfunc
;
641 time_t lastthreadrestarttime
;
643 char lastnodewhichkeyedusup
[MAXNODESTR
];
644 int dtmf_local_timer
;
645 char dtmf_local_str
[100];
646 struct ast_filestream
*monstream
;
652 time_t start_time
,last_activity_time
;
667 } filters
[MAXFILTERS
];
669 #ifdef _MDC_DECODE_H_
671 unsigned short lastunit
;
676 struct nodelog
*next
;
677 struct nodelog
*prev
;
679 char archivedir
[MAXNODESTR
];
680 char str
[MAXNODESTR
* 2];
683 static int service_scan(struct rpt
*myrpt
);
684 static int set_mode_ft897(struct rpt
*myrpt
, char newmode
);
685 static int set_mode_ic706(struct rpt
*myrpt
, char newmode
);
686 static int simple_command_ft897(struct rpt
*myrpt
, char command
);
687 static int setrem(struct rpt
*myrpt
);
689 AST_MUTEX_DEFINE_STATIC(nodeloglock
);
691 AST_MUTEX_DEFINE_STATIC(nodelookuplock
);
693 #ifdef APP_RPT_LOCK_DEBUG
695 #warning COMPILING WITH LOCK-DEBUGGING ENABLED!!
697 #define MAXLOCKTHREAD 100
699 #define rpt_mutex_lock(x) _rpt_mutex_lock(x,myrpt,__LINE__)
700 #define rpt_mutex_unlock(x) _rpt_mutex_unlock(x,myrpt,__LINE__)
708 } lockthreads
[MAXLOCKTHREAD
];
716 struct lockthread lockthread
;
719 int lock_ring_index
= 0;
721 AST_MUTEX_DEFINE_STATIC(locklock
);
723 static struct lockthread
*get_lockthread(pthread_t id
)
727 for(i
= 0; i
< MAXLOCKTHREAD
; i
++)
729 if (lockthreads
[i
].id
== id
) return(&lockthreads
[i
]);
734 static struct lockthread
*put_lockthread(pthread_t id
)
738 for(i
= 0; i
< MAXLOCKTHREAD
; i
++)
740 if (lockthreads
[i
].id
== id
)
741 return(&lockthreads
[i
]);
743 for(i
= 0; i
< MAXLOCKTHREAD
; i
++)
745 if (!lockthreads
[i
].id
)
747 lockthreads
[i
].lockcount
= 0;
748 lockthreads
[i
].lastlock
= 0;
749 lockthreads
[i
].lastunlock
= 0;
750 lockthreads
[i
].id
= id
;
751 return(&lockthreads
[i
]);
758 static void rpt_mutex_spew(void)
760 struct by_lightning lock_ring_copy
[32];
761 int lock_ring_index_copy
;
765 struct timeval lasttv
;
767 ast_mutex_lock(&locklock
);
768 memcpy(&lock_ring_copy
, &lock_ring
, sizeof(lock_ring_copy
));
769 lock_ring_index_copy
= lock_ring_index
;
770 ast_mutex_unlock(&locklock
);
772 lasttv
.tv_sec
= lasttv
.tv_usec
= 0;
773 for(i
= 0 ; i
< 32 ; i
++)
775 j
= (i
+ lock_ring_index_copy
) % 32;
776 strftime(a
,sizeof(a
) - 1,"%m/%d/%Y %H:%M:%S",
777 localtime(&lock_ring_copy
[j
].tv
.tv_sec
));
781 diff
= (lock_ring_copy
[j
].tv
.tv_sec
- lasttv
.tv_sec
)
783 diff
+= (lock_ring_copy
[j
].tv
.tv_usec
- lasttv
.tv_usec
);
785 lasttv
.tv_sec
= lock_ring_copy
[j
].tv
.tv_sec
;
786 lasttv
.tv_usec
= lock_ring_copy
[j
].tv
.tv_usec
;
787 if (!lock_ring_copy
[j
].tv
.tv_sec
) continue;
788 if (lock_ring_copy
[j
].line
< 0)
790 ast_log(LOG_NOTICE
,"LOCKDEBUG [#%d] UNLOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
791 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
);
795 ast_log(LOG_NOTICE
,"LOCKDEBUG [#%d] LOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
796 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
);
802 static void _rpt_mutex_lock(ast_mutex_t
*lockp
, struct rpt
*myrpt
, int line
)
804 struct lockthread
*t
;
808 ast_mutex_lock(&locklock
);
809 t
= put_lockthread(id
);
812 ast_mutex_unlock(&locklock
);
817 int lastline
= t
->lastlock
;
818 ast_mutex_unlock(&locklock
);
819 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
);
825 gettimeofday(&lock_ring
[lock_ring_index
].tv
, NULL
);
826 lock_ring
[lock_ring_index
].rpt
= myrpt
;
827 memcpy(&lock_ring
[lock_ring_index
].lockthread
,t
,sizeof(struct lockthread
));
828 lock_ring
[lock_ring_index
++].line
= line
;
829 if(lock_ring_index
== 32)
831 ast_mutex_unlock(&locklock
);
832 ast_mutex_lock(lockp
);
836 static void _rpt_mutex_unlock(ast_mutex_t
*lockp
, struct rpt
*myrpt
, int line
)
838 struct lockthread
*t
;
842 ast_mutex_lock(&locklock
);
843 t
= put_lockthread(id
);
846 ast_mutex_unlock(&locklock
);
851 int lastline
= t
->lastunlock
;
852 ast_mutex_unlock(&locklock
);
853 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
);
857 t
->lastunlock
= line
;
859 gettimeofday(&lock_ring
[lock_ring_index
].tv
, NULL
);
860 lock_ring
[lock_ring_index
].rpt
= myrpt
;
861 memcpy(&lock_ring
[lock_ring_index
].lockthread
,t
,sizeof(struct lockthread
));
862 lock_ring
[lock_ring_index
++].line
= -line
;
863 if(lock_ring_index
== 32)
865 ast_mutex_unlock(&locklock
);
866 ast_mutex_unlock(lockp
);
869 #else /* APP_RPT_LOCK_DEBUG */
871 #define rpt_mutex_lock(x) ast_mutex_lock(x)
872 #define rpt_mutex_unlock(x) ast_mutex_unlock(x)
874 #endif /* APP_RPT_LOCK_DEBUG */
877 * Return 1 if rig is multimode capable
880 static int multimode_capable(struct rpt
*myrpt
)
882 if(!strcmp(myrpt
->remote
, remote_rig_ft897
))
884 if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
894 static int rpt_do_debug(int fd
, int argc
, char *argv
[]);
895 static int rpt_do_dump(int fd
, int argc
, char *argv
[]);
896 static int rpt_do_stats(int fd
, int argc
, char *argv
[]);
897 static int rpt_do_lstats(int fd
, int argc
, char *argv
[]);
898 static int rpt_do_nodes(int fd
, int argc
, char *argv
[]);
899 static int rpt_do_reload(int fd
, int argc
, char *argv
[]);
900 static int rpt_do_restart(int fd
, int argc
, char *argv
[]);
901 static int rpt_do_fun(int fd
, int argc
, char *argv
[]);
903 static char debug_usage
[] =
904 "Usage: rpt debug level {0-7}\n"
905 " Enables debug messages in app_rpt\n";
907 static char dump_usage
[] =
908 "Usage: rpt dump <nodename>\n"
909 " Dumps struct debug info to log\n";
911 static char dump_stats
[] =
912 "Usage: rpt stats <nodename>\n"
913 " Dumps node statistics to console\n";
915 static char dump_lstats
[] =
916 "Usage: rpt lstats <nodename>\n"
917 " Dumps link statistics to console\n";
919 static char dump_nodes
[] =
920 "Usage: rpt nodes <nodename>\n"
921 " Dumps a list of directly and indirectly connected nodes to the console\n";
923 static char reload_usage
[] =
924 "Usage: rpt reload\n"
925 " Reloads app_rpt running config parameters\n";
927 static char restart_usage
[] =
928 "Usage: rpt restart\n"
929 " Restarts app_rpt\n";
931 static char fun_usage
[] =
932 "Usage: rpt fun <nodename> <command>\n"
933 " Send a DTMF function to a node\n";
936 static struct ast_cli_entry cli_debug
=
937 { { "rpt", "debug", "level" }, rpt_do_debug
,
938 "Enable app_rpt debugging", debug_usage
};
940 static struct ast_cli_entry cli_dump
=
941 { { "rpt", "dump" }, rpt_do_dump
,
942 "Dump app_rpt structs for debugging", dump_usage
};
944 static struct ast_cli_entry cli_stats
=
945 { { "rpt", "stats" }, rpt_do_stats
,
946 "Dump node statistics", dump_stats
};
948 static struct ast_cli_entry cli_nodes
=
949 { { "rpt", "nodes" }, rpt_do_nodes
,
950 "Dump node list", dump_nodes
};
952 static struct ast_cli_entry cli_lstats
=
953 { { "rpt", "lstats" }, rpt_do_lstats
,
954 "Dump link statistics", dump_lstats
};
956 static struct ast_cli_entry cli_reload
=
957 { { "rpt", "reload" }, rpt_do_reload
,
958 "Reload app_rpt config", reload_usage
};
960 static struct ast_cli_entry cli_restart
=
961 { { "rpt", "restart" }, rpt_do_restart
,
962 "Restart app_rpt", restart_usage
};
964 static struct ast_cli_entry cli_fun
=
965 { { "rpt", "fun" }, rpt_do_fun
,
966 "Execute a DTMF function", fun_usage
};
973 static struct telem_defaults tele_defs
[] = {
974 {"ct1","|t(350,0,100,3072)(500,0,100,3072)(660,0,100,3072)"},
975 {"ct2","|t(660,880,150,3072)"},
976 {"ct3","|t(440,0,150,3072)"},
977 {"ct4","|t(550,0,150,3072)"},
978 {"ct5","|t(660,0,150,3072)"},
979 {"ct6","|t(880,0,150,3072)"},
980 {"ct7","|t(660,440,150,3072)"},
981 {"ct8","|t(700,1100,150,3072)"},
982 {"remotemon","|t(1600,0,75,2048)"},
983 {"remotetx","|t(2000,0,75,2048)(0,0,75,0)(1600,0,75,2048)"},
984 {"cmdmode","|t(900,904,200,2048)"},
985 {"functcomplete","|t(1000,0,100,2048)(0,0,100,0)(1000,0,100,2048)"}
989 * Forward decl's - these suppress compiler warnings when funcs coded further down the file than thier invokation
992 static int setrbi(struct rpt
*myrpt
);
993 static int set_ft897(struct rpt
*myrpt
);
994 static int set_ic706(struct rpt
*myrpt
);
995 static int setkenwood(struct rpt
*myrpt
);
996 static int setrbi_check(struct rpt
*myrpt
);
1001 * Define function protos for function table here
1004 static int function_ilink(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
);
1005 static int function_autopatchup(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
);
1006 static int function_autopatchdn(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
);
1007 static int function_status(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
);
1008 static int function_cop(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
);
1009 static int function_remote(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
);
1010 static int function_macro(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
);
1015 static struct function_table_tag function_table
[] = {
1016 {"cop", function_cop
},
1017 {"autopatchup", function_autopatchup
},
1018 {"autopatchdn", function_autopatchdn
},
1019 {"ilink", function_ilink
},
1020 {"status", function_status
},
1021 {"remote", function_remote
},
1022 {"macro", function_macro
}
1025 static long diskavail(struct rpt
*myrpt
)
1027 struct statfs statfsbuf
;
1029 if (!myrpt
->p
.archivedir
) return(0);
1030 if (statfs(myrpt
->p
.archivedir
,&statfsbuf
) == -1)
1032 ast_log(LOG_WARNING
,"Cannot get filesystem size for %s node %s\n",
1033 myrpt
->p
.archivedir
,myrpt
->name
);
1036 return(statfsbuf
.f_bavail
);
1039 static void do_dtmf_phone(struct rpt
*myrpt
, struct rpt_link
*mylink
, char c
)
1043 l
= myrpt
->links
.next
;
1044 /* go thru all the links */
1045 while(l
!= &myrpt
->links
)
1052 /* dont send to self */
1053 if (mylink
&& (l
== mylink
))
1058 if (l
->chan
) ast_senddigit(l
->chan
,c
);
1064 /* node logging function */
1065 static void donodelog(struct rpt
*myrpt
,char *str
)
1067 struct nodelog
*nodep
;
1070 if (!myrpt
->p
.archivedir
) return;
1071 nodep
= (struct nodelog
*)malloc(sizeof(struct nodelog
));
1074 ast_log(LOG_ERROR
,"Cannot get memory for node log");
1077 time(&nodep
->timestamp
);
1078 strncpy(nodep
->archivedir
,myrpt
->p
.archivedir
,
1079 sizeof(nodep
->archivedir
) - 1);
1080 strftime(datestr
,sizeof(datestr
) - 1,"%Y%m%d%H%M%S",
1081 localtime(&nodep
->timestamp
));
1082 snprintf(nodep
->str
,sizeof(nodep
->str
) - 1,"%s %s,%s\n",
1083 myrpt
->name
,datestr
,str
);
1084 ast_mutex_lock(&nodeloglock
);
1085 insque((struct qelem
*) nodep
, (struct qelem
*) nodelog
.prev
);
1086 ast_mutex_unlock(&nodeloglock
);
1089 /* must be called locked */
1090 static void do_dtmf_local(struct rpt
*myrpt
, char c
)
1094 static const char* dtmf_tones
[] = {
1095 "!941+1336/200,!0/200", /* 0 */
1096 "!697+1209/200,!0/200", /* 1 */
1097 "!697+1336/200,!0/200", /* 2 */
1098 "!697+1477/200,!0/200", /* 3 */
1099 "!770+1209/200,!0/200", /* 4 */
1100 "!770+1336/200,!0/200", /* 5 */
1101 "!770+1477/200,!0/200", /* 6 */
1102 "!852+1209/200,!0/200", /* 7 */
1103 "!852+1336/200,!0/200", /* 8 */
1104 "!852+1477/200,!0/200", /* 9 */
1105 "!697+1633/200,!0/200", /* A */
1106 "!770+1633/200,!0/200", /* B */
1107 "!852+1633/200,!0/200", /* C */
1108 "!941+1633/200,!0/200", /* D */
1109 "!941+1209/200,!0/200", /* * */
1110 "!941+1477/200,!0/200" }; /* # */
1115 snprintf(myrpt
->dtmf_local_str
+ strlen(myrpt
->dtmf_local_str
),sizeof(myrpt
->dtmf_local_str
) - 1,"%c",c
);
1116 if (!myrpt
->dtmf_local_timer
)
1117 myrpt
->dtmf_local_timer
= DTMF_LOCAL_STARTTIME
;
1120 if (myrpt
->dtmf_local_timer
== 1)
1122 /* if anything in the string */
1123 if (myrpt
->dtmf_local_str
[0])
1125 digit
= myrpt
->dtmf_local_str
[0];
1126 myrpt
->dtmf_local_str
[0] = 0;
1127 for(i
= 1; myrpt
->dtmf_local_str
[i
]; i
++)
1129 myrpt
->dtmf_local_str
[i
- 1] =
1130 myrpt
->dtmf_local_str
[i
];
1132 myrpt
->dtmf_local_str
[i
- 1] = 0;
1133 myrpt
->dtmf_local_timer
= DTMF_LOCAL_TIME
;
1134 rpt_mutex_unlock(&myrpt
->lock
);
1135 if (digit
>= '0' && digit
<='9')
1136 ast_playtones_start(myrpt
->txchannel
, 0, dtmf_tones
[digit
-'0'], 0);
1137 else if (digit
>= 'A' && digit
<= 'D')
1138 ast_playtones_start(myrpt
->txchannel
, 0, dtmf_tones
[digit
-'A'+10], 0);
1139 else if (digit
== '*')
1140 ast_playtones_start(myrpt
->txchannel
, 0, dtmf_tones
[14], 0);
1141 else if (digit
== '#')
1142 ast_playtones_start(myrpt
->txchannel
, 0, dtmf_tones
[15], 0);
1145 ast_log(LOG_DEBUG
, "Unable to generate DTMF tone '%c' for '%s'\n", digit
, myrpt
->txchannel
->name
);
1147 rpt_mutex_lock(&myrpt
->lock
);
1151 myrpt
->dtmf_local_timer
= 0;
1156 static int openserial(char *fname
)
1158 struct termios mode
;
1161 fd
= open(fname
,O_RDWR
);
1164 ast_log(LOG_WARNING
,"Cannot open serial port %s\n",fname
);
1167 memset(&mode
, 0, sizeof(mode
));
1168 if (tcgetattr(fd
, &mode
)) {
1169 ast_log(LOG_WARNING
, "Unable to get serial parameters on %s: %s\n", fname
, strerror(errno
));
1175 mode
.c_iflag
&= ~(IGNBRK
|BRKINT
|PARMRK
|ISTRIP
1176 |INLCR
|IGNCR
|ICRNL
|IXON
);
1177 mode
.c_oflag
&= ~OPOST
;
1178 mode
.c_lflag
&= ~(ECHO
|ECHONL
|ICANON
|ISIG
|IEXTEN
);
1179 mode
.c_cflag
&= ~(CSIZE
|PARENB
|CRTSCTS
);
1180 mode
.c_cflag
|= CS8
;
1181 mode
.c_cc
[TIME
] = 3;
1185 cfsetispeed(&mode
, B9600
);
1186 cfsetospeed(&mode
, B9600
);
1187 if (tcsetattr(fd
, TCSANOW
, &mode
))
1188 ast_log(LOG_WARNING
, "Unable to set serial parameters on %s: %s\n", fname
, strerror(errno
));
1192 static void mdc1200_notify(struct rpt
*myrpt
,char *fromnode
, unsigned int unit
)
1196 ast_verbose("Got MDC-1200 ID %04X from local system (%s)\n",
1201 ast_verbose("Got MDC-1200 ID %04X from node %s (%s)\n",
1202 unit
,fromnode
,myrpt
->name
);
1206 #ifdef _MDC_DECODE_H_
1208 static void mdc1200_send(struct rpt
*myrpt
, unsigned int unit
)
1211 struct ast_frame wf
;
1215 sprintf(str
,"I %s %04X",myrpt
->name
,unit
);
1217 wf
.frametype
= AST_FRAME_TEXT
;
1221 wf
.datalen
= strlen(str
) + 1;
1225 l
= myrpt
->links
.next
;
1226 /* otherwise, send it to all of em */
1227 while(l
!= &myrpt
->links
)
1229 if (l
->name
[0] == '0')
1235 if (l
->chan
) ast_write(l
->chan
,&wf
);
1243 static char func_xlat(struct rpt
*myrpt
,char c
,struct rpt_xlat
*xlat
)
1250 /* if too much time, reset the skate machine */
1251 if ((now
- xlat
->lastone
) > MAXXLATTIME
)
1253 xlat
->funcindex
= xlat
->endindex
= 0;
1255 if (xlat
->funccharseq
[0] && (c
== xlat
->funccharseq
[xlat
->funcindex
++]))
1257 time(&xlat
->lastone
);
1259 if (!xlat
->funccharseq
[xlat
->funcindex
])
1261 xlat
->funcindex
= xlat
->endindex
= 0;
1262 return(myrpt
->p
.funcchar
);
1264 } else xlat
->funcindex
= 0;
1265 if (xlat
->endcharseq
[0] && (c
== xlat
->endcharseq
[xlat
->endindex
++]))
1267 time(&xlat
->lastone
);
1269 if (!xlat
->endcharseq
[xlat
->endindex
])
1271 xlat
->funcindex
= xlat
->endindex
= 0;
1272 return(myrpt
->p
.endchar
);
1274 } else xlat
->endindex
= 0;
1275 /* if in middle of decode seq, send nothing back */
1276 if (gotone
) return(0);
1277 /* if no pass chars specified, return em all */
1278 if (!xlat
->passchars
[0]) return(c
);
1279 /* if a "pass char", pass it */
1280 if (strchr(xlat
->passchars
,c
)) return(c
);
1285 * Return a pointer to the first non-whitespace character
1288 static char *eatwhite(char *s
)
1290 while((*s
== ' ') || (*s
== 0x09)){ /* get rid of any leading white space */
1299 * Break up a delimited string into a table of substrings
1301 * str - delimited string ( will be modified )
1302 * strp- list of pointers to substrings (this is built by this function), NULL will be placed at end of list
1303 * limit- maximum number of substrings to process
1308 static int finddelim(char *str
, char *strp
[], int limit
)
1320 for(l
= 0; *str
&& (l
< limit
) ; str
++)
1322 if (*str
== QUOTECHR
)
1331 strp
[i
- 1] = str
+ 1;
1335 if ((*str
== DELIMCHR
) && (!inquo
))
1339 strp
[i
++] = str
+ 1;
1347 /* must be called locked */
1348 static void __mklinklist(struct rpt
*myrpt
, struct rpt_link
*mylink
, char *buf
)
1354 buf
[0] = 0; /* clear output buffer */
1355 /* go thru all links */
1356 for(l
= myrpt
->links
.next
; l
!= &myrpt
->links
; l
= l
->next
)
1358 /* if is not a real link, ignore it */
1359 if (l
->name
[0] == '0') continue;
1360 /* dont count our stuff */
1361 if (l
== mylink
) continue;
1362 if (mylink
&& (!strcmp(l
->name
,mylink
->name
))) continue;
1363 /* figure out mode to report */
1364 mode
= 'T'; /* use Tranceive by default */
1365 if (!l
->mode
) mode
= 'R'; /* indicate RX for our mode */
1366 if (!l
->thisconnected
) mode
= 'C'; /* indicate connecting */
1367 spos
= strlen(buf
); /* current buf size (b4 we add our stuff) */
1373 /* add nodes into buffer */
1376 snprintf(buf
+ spos
,MAXLINKLIST
- spos
,
1377 "%c%s,%s",mode
,l
->name
,l
->linklist
);
1379 else /* if no nodes, add this node into buffer */
1381 snprintf(buf
+ spos
,MAXLINKLIST
- spos
,
1382 "%c%s",mode
,l
->name
);
1384 /* if we are in tranceive mode, let all modes stand */
1385 if (mode
== 'T') continue;
1386 /* downgrade everyone on this node if appropriate */
1387 for(i
= spos
; buf
[i
]; i
++)
1389 if (buf
[i
] == 'T') buf
[i
] = mode
;
1390 if ((buf
[i
] == 'R') && (mode
== 'C')) buf
[i
] = mode
;
1396 /* must be called locked */
1397 static void __kickshort(struct rpt
*myrpt
)
1401 for(l
= myrpt
->links
.next
; l
!= &myrpt
->links
; l
= l
->next
)
1403 /* if is not a real link, ignore it */
1404 if (l
->name
[0] == '0') continue;
1405 l
->linklisttimer
= LINKLISTSHORTTIME
;
1410 static char *node_lookup(struct rpt
*myrpt
,char *digitbuf
)
1416 static time_t last
= 0;
1417 static struct ast_config
*ourcfg
= NULL
;
1418 struct ast_variable
*vp
;
1420 /* try to look it up locally first */
1421 val
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->p
.nodes
, digitbuf
);
1422 if (val
) return(val
);
1423 ast_mutex_lock(&nodelookuplock
);
1424 /* if file does not exist */
1425 if (stat(myrpt
->p
.extnodefile
,&mystat
) == -1)
1427 if (ourcfg
) ast_config_destroy(ourcfg
);
1429 ast_mutex_unlock(&nodelookuplock
);
1432 /* if we need to reload */
1433 if (mystat
.st_mtime
> last
)
1435 if (ourcfg
) ast_config_destroy(ourcfg
);
1436 ourcfg
= ast_config_load(myrpt
->p
.extnodefile
);
1437 /* if file not there, just bail */
1440 ast_mutex_unlock(&nodelookuplock
);
1443 /* reset "last" time */
1444 last
= mystat
.st_mtime
;
1446 /* determine longest node length again */
1448 vp
= ast_variable_browse(myrpt
->cfg
, myrpt
->p
.nodes
);
1450 j
= strlen(vp
->name
);
1451 if (j
> longestnode
)
1456 vp
= ast_variable_browse(ourcfg
, myrpt
->p
.extnodes
);
1458 j
= strlen(vp
->name
);
1459 if (j
> longestnode
)
1464 myrpt
->longestnode
= longestnode
;
1468 val
= (char *) ast_variable_retrieve(ourcfg
, myrpt
->p
.extnodes
, digitbuf
);
1469 ast_mutex_unlock(&nodelookuplock
);
1474 * Match a keyword in a list, and return index of string plus 1 if there was a match,* else return 0.
1475 * If param is passed in non-null, then it will be set to the first character past the match
1478 static int matchkeyword(char *string
, char **param
, char *keywords
[])
1481 for( i
= 0 ; keywords
[i
] ; i
++){
1482 ls
= strlen(keywords
[i
]);
1487 if(!strncmp(string
, keywords
[i
], ls
)){
1489 *param
= string
+ ls
;
1498 * Skip characters in string which are in charlist, and return a pointer to the
1499 * first non-matching character
1502 static char *skipchars(char *string
, char *charlist
)
1506 for(i
= 0; charlist
[i
] ; i
++){
1507 if(*string
== charlist
[i
]){
1520 static int myatoi(char *str
)
1524 if (str
== NULL
) return -1;
1525 /* leave this %i alone, non-base-10 input is useful here */
1526 if (sscanf(str
,"%i",&ret
) != 1) return -1;
1530 static int mycompar(const void *a
, const void *b
)
1532 char **x
= (char **) a
;
1533 char **y
= (char **) b
;
1536 if ((**x
< '0') || (**x
> '9')) xoff
= 1; else xoff
= 0;
1537 if ((**y
< '0') || (**y
> '9')) yoff
= 1; else yoff
= 0;
1538 return(strcmp((*x
) + xoff
,(*y
) + yoff
));
1543 /* rpt filter routine */
1544 static void rpt_filter(struct rpt
*myrpt
, volatile short *buf
, int len
)
1547 struct rptfilter
*f
;
1549 for(i
= 0; i
< len
; i
++)
1551 for(j
= 0; j
< MAXFILTERS
; j
++)
1553 f
= &myrpt
->filters
[j
];
1554 if (!*f
->desc
) continue;
1555 f
->x0
= f
->x1
; f
->x1
= f
->x2
;
1556 f
->x2
= ((float)buf
[i
]) / f
->gain
;
1557 f
->y0
= f
->y1
; f
->y1
= f
->y2
;
1558 f
->y2
= (f
->x0
+ f
->x2
) + f
->const0
* f
->x1
1559 + (f
->const1
* f
->y0
) + (f
->const2
* f
->y1
);
1560 buf
[i
] = (short)f
->y2
;
1569 Get the time for the machine's time zone
1570 Note: Asterisk requires a copy of localtime
1571 in the /etc directory for this to work properly.
1572 If /etc/localtime is not present, you will get
1573 GMT time! This is especially important on systems
1574 running embedded linux distributions as they don't usually
1575 have support for locales.
1577 If OLD_ASTERISK is defined, then the older localtime_r
1578 function will be used. The /etc/localtime file is not
1579 required in this case. This provides backward compatibility
1580 with Asterisk 1.2 systems.
1584 static void rpt_localtime( time_t * t
, struct tm
*lt
)
1589 ast_localtime(t
, lt
, NULL
);
1593 /* Retrieve an int from a config file */
1595 static int retrieve_astcfgint(struct rpt
*myrpt
,char *category
, char *name
, int min
, int max
, int defl
)
1599 char include_zero
= 0;
1601 if(min
< 0){ /* If min is negative, this means include 0 as a valid entry */
1606 var
= (char *) ast_variable_retrieve(myrpt
->cfg
, category
, name
);
1609 if(include_zero
&& !ret
)
1622 static void load_rpt_vars(int n
,int init
)
1625 int i
,j
,longestnode
;
1626 struct ast_variable
*vp
;
1627 struct ast_config
*cfg
;
1630 static char *cs_keywords
[] = {"rptena","rptdis","apena","apdis","lnkena","lnkdis","totena","totdis","skena","skdis",
1631 "ufena","ufdis","atena","atdis",NULL
};
1633 if (option_verbose
> 2)
1634 ast_verbose(VERBOSE_PREFIX_3
"%s config for repeater %s\n",
1635 (init
) ? "Loading initial" : "Re-Loading",rpt_vars
[n
].name
);
1636 ast_mutex_lock(&rpt_vars
[n
].lock
);
1637 if (rpt_vars
[n
].cfg
) ast_config_destroy(rpt_vars
[n
].cfg
);
1638 cfg
= ast_config_load("rpt.conf");
1640 ast_mutex_unlock(&rpt_vars
[n
].lock
);
1641 ast_log(LOG_NOTICE
, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
1644 rpt_vars
[n
].cfg
= cfg
;
1645 this = rpt_vars
[n
].name
;
1646 memset(&rpt_vars
[n
].p
,0,sizeof(rpt_vars
[n
].p
));
1649 /* clear all the fields in the structure after 'p' */
1650 memset(&rpt_vars
[n
].p
+ sizeof(rpt_vars
[0].p
), 0, sizeof(rpt_vars
[0]) - sizeof(rpt_vars
[0].p
) - offsetof(typeof(rpt_vars
[0]), p
));
1651 rpt_vars
[n
].tele
.next
= &rpt_vars
[n
].tele
;
1652 rpt_vars
[n
].tele
.prev
= &rpt_vars
[n
].tele
;
1653 rpt_vars
[n
].rpt_thread
= AST_PTHREADT_NULL
;
1654 rpt_vars
[n
].tailmessagen
= 0;
1657 /* zot out filters stuff */
1658 memset(&rpt_vars
[n
].filters
,0,sizeof(rpt_vars
[n
].filters
));
1660 val
= (char *) ast_variable_retrieve(cfg
,this,"context");
1661 if (val
) rpt_vars
[n
].p
.ourcontext
= val
;
1662 else rpt_vars
[n
].p
.ourcontext
= this;
1663 val
= (char *) ast_variable_retrieve(cfg
,this,"callerid");
1664 if (val
) rpt_vars
[n
].p
.ourcallerid
= val
;
1665 val
= (char *) ast_variable_retrieve(cfg
,this,"accountcode");
1666 if (val
) rpt_vars
[n
].p
.acctcode
= val
;
1667 val
= (char *) ast_variable_retrieve(cfg
,this,"idrecording");
1668 if (val
) rpt_vars
[n
].p
.ident
= val
;
1669 val
= (char *) ast_variable_retrieve(cfg
,this,"hangtime");
1670 if (val
) rpt_vars
[n
].p
.hangtime
= atoi(val
);
1671 else rpt_vars
[n
].p
.hangtime
= HANGTIME
;
1672 val
= (char *) ast_variable_retrieve(cfg
,this,"althangtime");
1673 if (val
) rpt_vars
[n
].p
.althangtime
= atoi(val
);
1674 else rpt_vars
[n
].p
.althangtime
= HANGTIME
;
1675 val
= (char *) ast_variable_retrieve(cfg
,this,"totime");
1676 if (val
) rpt_vars
[n
].p
.totime
= atoi(val
);
1677 else rpt_vars
[n
].p
.totime
= TOTIME
;
1678 rpt_vars
[n
].p
.tailmessagetime
= retrieve_astcfgint(&rpt_vars
[n
],this, "tailmessagetime", 0, 2400000, 0);
1679 rpt_vars
[n
].p
.tailsquashedtime
= retrieve_astcfgint(&rpt_vars
[n
],this, "tailsquashedtime", 0, 2400000, 0);
1680 rpt_vars
[n
].p
.duplex
= retrieve_astcfgint(&rpt_vars
[n
],this,"duplex",0,4,2);
1681 rpt_vars
[n
].p
.idtime
= retrieve_astcfgint(&rpt_vars
[n
],this, "idtime", -60000, 2400000, IDTIME
); /* Enforce a min max including zero */
1682 rpt_vars
[n
].p
.politeid
= retrieve_astcfgint(&rpt_vars
[n
],this, "politeid", 30000, 300000, POLITEID
); /* Enforce a min max */
1683 val
= (char *) ast_variable_retrieve(cfg
,this,"tonezone");
1684 if (val
) rpt_vars
[n
].p
.tonezone
= val
;
1685 rpt_vars
[n
].p
.tailmessages
[0] = 0;
1686 rpt_vars
[n
].p
.tailmessagemax
= 0;
1687 val
= (char *) ast_variable_retrieve(cfg
,this,"tailmessagelist");
1688 if (val
) rpt_vars
[n
].p
.tailmessagemax
= finddelim(val
, rpt_vars
[n
].p
.tailmessages
, 500);
1689 val
= (char *) ast_variable_retrieve(cfg
,this,"memory");
1690 if (!val
) val
= MEMORY
;
1691 rpt_vars
[n
].p
.memory
= val
;
1692 val
= (char *) ast_variable_retrieve(cfg
,this,"macro");
1693 if (!val
) val
= MACRO
;
1694 rpt_vars
[n
].p
.macro
= val
;
1695 val
= (char *) ast_variable_retrieve(cfg
,this,"startup_macro");
1696 if (val
) rpt_vars
[n
].p
.startupmacro
= val
;
1697 val
= (char *) ast_variable_retrieve(cfg
,this,"iobase");
1698 /* do not use atoi() here, we need to be able to have
1699 the input specified in hex or decimal so we use
1701 if ((!val
) || (sscanf(val
,"%i",&rpt_vars
[n
].p
.iobase
) != 1))
1702 rpt_vars
[n
].p
.iobase
= DEFAULT_IOBASE
;
1703 val
= (char *) ast_variable_retrieve(cfg
,this,"ioport");
1704 rpt_vars
[n
].p
.ioport
= val
;
1705 val
= (char *) ast_variable_retrieve(cfg
,this,"functions");
1709 rpt_vars
[n
].p
.simple
= 1;
1711 rpt_vars
[n
].p
.functions
= val
;
1712 val
= (char *) ast_variable_retrieve(cfg
,this,"link_functions");
1713 if (val
) rpt_vars
[n
].p
.link_functions
= val
;
1715 rpt_vars
[n
].p
.link_functions
= rpt_vars
[n
].p
.functions
;
1716 val
= (char *) ast_variable_retrieve(cfg
,this,"phone_functions");
1717 if (val
) rpt_vars
[n
].p
.phone_functions
= val
;
1718 val
= (char *) ast_variable_retrieve(cfg
,this,"dphone_functions");
1719 if (val
) rpt_vars
[n
].p
.dphone_functions
= val
;
1720 val
= (char *) ast_variable_retrieve(cfg
,this,"funcchar");
1721 if (!val
) rpt_vars
[n
].p
.funcchar
= FUNCCHAR
; else
1722 rpt_vars
[n
].p
.funcchar
= *val
;
1723 val
= (char *) ast_variable_retrieve(cfg
,this,"endchar");
1724 if (!val
) rpt_vars
[n
].p
.endchar
= ENDCHAR
; else
1725 rpt_vars
[n
].p
.endchar
= *val
;
1726 val
= (char *) ast_variable_retrieve(cfg
,this,"nobusyout");
1727 if (val
) rpt_vars
[n
].p
.nobusyout
= ast_true(val
);
1728 val
= (char *) ast_variable_retrieve(cfg
,this,"notelemtx");
1729 if (val
) rpt_vars
[n
].p
.notelemtx
= ast_true(val
);
1730 val
= (char *) ast_variable_retrieve(cfg
,this,"propagate_dtmf");
1731 if (val
) rpt_vars
[n
].p
.propagate_dtmf
= ast_true(val
);
1732 val
= (char *) ast_variable_retrieve(cfg
,this,"propagate_phonedtmf");
1733 if (val
) rpt_vars
[n
].p
.propagate_phonedtmf
= ast_true(val
);
1734 val
= (char *) ast_variable_retrieve(cfg
,this,"linktolink");
1735 if (val
) rpt_vars
[n
].p
.linktolink
= ast_true(val
);
1736 val
= (char *) ast_variable_retrieve(cfg
,this,"nodes");
1737 if (!val
) val
= NODES
;
1738 rpt_vars
[n
].p
.nodes
= val
;
1739 val
= (char *) ast_variable_retrieve(cfg
,this,"extnodes");
1740 if (!val
) val
= EXTNODES
;
1741 rpt_vars
[n
].p
.extnodes
= val
;
1742 val
= (char *) ast_variable_retrieve(cfg
,this,"extnodefile");
1743 if (!val
) val
= EXTNODEFILE
;
1744 rpt_vars
[n
].p
.extnodefile
= val
;
1745 val
= (char *) ast_variable_retrieve(cfg
,this,"archivedir");
1746 if (val
) rpt_vars
[n
].p
.archivedir
= val
;
1747 val
= (char *) ast_variable_retrieve(cfg
,this,"authlevel");
1748 if (val
) rpt_vars
[n
].p
.authlevel
= atoi(val
);
1749 else rpt_vars
[n
].p
.authlevel
= 0;
1750 val
= (char *) ast_variable_retrieve(cfg
,this,"monminblocks");
1751 if (val
) rpt_vars
[n
].p
.monminblocks
= atol(val
);
1752 else rpt_vars
[n
].p
.monminblocks
= DEFAULT_MONITOR_MIN_DISK_BLOCKS
;
1753 val
= (char *) ast_variable_retrieve(cfg
,this,"remote_inact_timeout");
1754 if (val
) rpt_vars
[n
].p
.remoteinacttimeout
= atoi(val
);
1755 else rpt_vars
[n
].p
.remoteinacttimeout
= DEFAULT_REMOTE_INACT_TIMEOUT
;
1756 val
= (char *) ast_variable_retrieve(cfg
,this,"civaddr");
1757 if (val
) rpt_vars
[n
].p
.civaddr
= atoi(val
);
1758 else rpt_vars
[n
].p
.civaddr
= DEFAULT_CIV_ADDR
;
1759 val
= (char *) ast_variable_retrieve(cfg
,this,"remote_timeout");
1760 if (val
) rpt_vars
[n
].p
.remotetimeout
= atoi(val
);
1761 else rpt_vars
[n
].p
.remotetimeout
= DEFAULT_REMOTE_TIMEOUT
;
1762 val
= (char *) ast_variable_retrieve(cfg
,this,"remote_timeout_warning");
1763 if (val
) rpt_vars
[n
].p
.remotetimeoutwarning
= atoi(val
);
1764 else rpt_vars
[n
].p
.remotetimeoutwarning
= DEFAULT_REMOTE_TIMEOUT_WARNING
;
1765 val
= (char *) ast_variable_retrieve(cfg
,this,"remote_timeout_warning_freq");
1766 if (val
) rpt_vars
[n
].p
.remotetimeoutwarningfreq
= atoi(val
);
1767 else rpt_vars
[n
].p
.remotetimeoutwarningfreq
= DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ
;
1769 val
= (char *) ast_variable_retrieve(cfg
,this,"rxnotch");
1771 i
= finddelim(val
,strs
,MAXFILTERS
* 2);
1772 i
&= ~1; /* force an even number, rounded down */
1773 if (i
>= 2) for(j
= 0; j
< i
; j
+= 2)
1775 rpt_mknotch(atof(strs
[j
]),atof(strs
[j
+ 1]),
1776 &rpt_vars
[n
].filters
[j
>> 1].gain
,
1777 &rpt_vars
[n
].filters
[j
>> 1].const0
,
1778 &rpt_vars
[n
].filters
[j
>> 1].const1
,
1779 &rpt_vars
[n
].filters
[j
>> 1].const2
);
1780 sprintf(rpt_vars
[n
].filters
[j
>> 1].desc
,"%s Hz, BW = %s",
1781 strs
[j
],strs
[j
+ 1]);
1786 val
= (char *) ast_variable_retrieve(cfg
,this,"inxlat");
1788 memset(&rpt_vars
[n
].p
.inxlat
,0,sizeof(struct rpt_xlat
));
1789 i
= finddelim(val
,strs
,3);
1790 if (i
) strncpy(rpt_vars
[n
].p
.inxlat
.funccharseq
,strs
[0],MAXXLAT
- 1);
1791 if (i
> 1) strncpy(rpt_vars
[n
].p
.inxlat
.endcharseq
,strs
[1],MAXXLAT
- 1);
1792 if (i
> 2) strncpy(rpt_vars
[n
].p
.inxlat
.passchars
,strs
[2],MAXXLAT
- 1);
1794 val
= (char *) ast_variable_retrieve(cfg
,this,"outxlat");
1796 memset(&rpt_vars
[n
].p
.outxlat
,0,sizeof(struct rpt_xlat
));
1797 i
= finddelim(val
,strs
,3);
1798 if (i
) strncpy(rpt_vars
[n
].p
.outxlat
.funccharseq
,strs
[0],MAXXLAT
- 1);
1799 if (i
> 1) strncpy(rpt_vars
[n
].p
.outxlat
.endcharseq
,strs
[1],MAXXLAT
- 1);
1800 if (i
> 2) strncpy(rpt_vars
[n
].p
.outxlat
.passchars
,strs
[2],MAXXLAT
- 1);
1802 /* retreive the stanza name for the control states if there is one */
1803 val
= (char *) ast_variable_retrieve(cfg
,this,"controlstates");
1804 rpt_vars
[n
].p
.csstanzaname
= val
;
1806 /* retreive the stanza name for the scheduler if there is one */
1807 val
= (char *) ast_variable_retrieve(cfg
,this,"scheduler");
1808 rpt_vars
[n
].p
.skedstanzaname
= val
;
1810 /* retreive the stanza name for the txlimits */
1811 val
= (char *) ast_variable_retrieve(cfg
,this,"txlimits");
1812 rpt_vars
[n
].p
.txlimitsstanzaname
= val
;
1816 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.nodes
);
1819 j
= strlen(vp
->name
);
1820 if (j
> longestnode
)
1825 rpt_vars
[n
].longestnode
= longestnode
;
1828 * For this repeater, Determine the length of the longest function
1830 rpt_vars
[n
].longestfunc
= 0;
1831 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.functions
);
1833 j
= strlen(vp
->name
);
1834 if (j
> rpt_vars
[n
].longestfunc
)
1835 rpt_vars
[n
].longestfunc
= j
;
1839 * For this repeater, Determine the length of the longest function
1841 rpt_vars
[n
].link_longestfunc
= 0;
1842 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.link_functions
);
1844 j
= strlen(vp
->name
);
1845 if (j
> rpt_vars
[n
].link_longestfunc
)
1846 rpt_vars
[n
].link_longestfunc
= j
;
1849 rpt_vars
[n
].phone_longestfunc
= 0;
1850 if (rpt_vars
[n
].p
.phone_functions
)
1852 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.phone_functions
);
1854 j
= strlen(vp
->name
);
1855 if (j
> rpt_vars
[n
].phone_longestfunc
)
1856 rpt_vars
[n
].phone_longestfunc
= j
;
1860 rpt_vars
[n
].dphone_longestfunc
= 0;
1861 if (rpt_vars
[n
].p
.dphone_functions
)
1863 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.dphone_functions
);
1865 j
= strlen(vp
->name
);
1866 if (j
> rpt_vars
[n
].dphone_longestfunc
)
1867 rpt_vars
[n
].dphone_longestfunc
= j
;
1871 rpt_vars
[n
].macro_longest
= 1;
1872 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.macro
);
1874 j
= strlen(vp
->name
);
1875 if (j
> rpt_vars
[n
].macro_longest
)
1876 rpt_vars
[n
].macro_longest
= j
;
1880 /* Browse for control states */
1881 if(rpt_vars
[n
].p
.csstanzaname
)
1882 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.csstanzaname
);
1885 for( i
= 0 ; vp
&& (i
< MAX_SYSSTATES
) ; i
++){ /* Iterate over the number of control state lines in the stanza */
1886 int k
,nukw
,statenum
;
1887 statenum
=atoi(vp
->name
);
1888 strncpy(s1
, vp
->value
, 255);
1890 nukw
= finddelim(s1
,strs
,32);
1892 for (k
= 0 ; k
< nukw
; k
++){ /* for each user specified keyword */
1893 for(j
= 0 ; cs_keywords
[j
] != NULL
; j
++){ /* try to match to one in our internal table */
1894 if(!strcmp(strs
[k
],cs_keywords
[j
])){
1896 case 0: /* rptena */
1897 rpt_vars
[n
].p
.s
[statenum
].txdisable
= 0;
1899 case 1: /* rptdis */
1900 rpt_vars
[n
].p
.s
[statenum
].txdisable
= 1;
1904 rpt_vars
[n
].p
.s
[statenum
].autopatchdisable
= 0;
1908 rpt_vars
[n
].p
.s
[statenum
].autopatchdisable
= 1;
1911 case 4: /* lnkena */
1912 rpt_vars
[n
].p
.s
[statenum
].linkfundisable
= 0;
1915 case 5: /* lnkdis */
1916 rpt_vars
[n
].p
.s
[statenum
].linkfundisable
= 1;
1919 case 6: /* totena */
1920 rpt_vars
[n
].p
.s
[statenum
].totdisable
= 0;
1923 case 7: /* totdis */
1924 rpt_vars
[n
].p
.s
[statenum
].totdisable
= 1;
1928 rpt_vars
[n
].p
.s
[statenum
].schedulerdisable
= 0;
1932 rpt_vars
[n
].p
.s
[statenum
].schedulerdisable
= 1;
1935 case 10: /* ufena */
1936 rpt_vars
[n
].p
.s
[statenum
].userfundisable
= 0;
1939 case 11: /* ufdis */
1940 rpt_vars
[n
].p
.s
[statenum
].userfundisable
= 1;
1943 case 12: /* atena */
1944 rpt_vars
[n
].p
.s
[statenum
].alternatetail
= 1;
1947 case 13: /* atdis */
1948 rpt_vars
[n
].p
.s
[statenum
].alternatetail
= 0;
1952 ast_log(LOG_WARNING
,
1953 "Unhandled control state keyword %s", cs_keywords
[i
]);
1961 ast_mutex_unlock(&rpt_vars
[n
].lock
);
1965 * Enable or disable debug output at a given level at the console
1968 static int rpt_do_debug(int fd
, int argc
, char *argv
[])
1973 return RESULT_SHOWUSAGE
;
1974 newlevel
= myatoi(argv
[3]);
1975 if((newlevel
< 0) || (newlevel
> 7))
1976 return RESULT_SHOWUSAGE
;
1978 ast_cli(fd
, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug
, newlevel
);
1980 ast_cli(fd
, "app_rpt Debugging disabled\n");
1983 return RESULT_SUCCESS
;
1987 * Dump rpt struct debugging onto console
1990 static int rpt_do_dump(int fd
, int argc
, char *argv
[])
1995 return RESULT_SHOWUSAGE
;
1997 for(i
= 0; i
< nrpts
; i
++)
1999 if (!strcmp(argv
[2],rpt_vars
[i
].name
))
2001 rpt_vars
[i
].disgorgetime
= time(NULL
) + 10; /* Do it 10 seconds later */
2002 ast_cli(fd
, "app_rpt struct dump requested for node %s\n",argv
[2]);
2003 return RESULT_SUCCESS
;
2006 return RESULT_FAILURE
;
2010 * Dump statistics onto console
2013 static int rpt_do_stats(int fd
, int argc
, char *argv
[])
2016 int dailytxtime
, dailykerchunks
;
2017 int totalkerchunks
, dailykeyups
, totalkeyups
, timeouts
;
2018 int totalexecdcommands
, dailyexecdcommands
, hours
, minutes
, seconds
;
2019 long long totaltxtime
;
2021 char *listoflinks
[MAX_STAT_LINKS
];
2022 char *lastnodewhichkeyedusup
, *lastdtmfcommand
;
2023 char *tot_state
, *ider_state
, *patch_state
;
2024 char *reverse_patch_state
, *sys_ena
, *tot_ena
, *link_ena
, *patch_ena
;
2025 char *sch_ena
, *input_signal
, *called_number
, *user_funs
, *tail_type
;
2028 static char *not_applicable
= "N/A";
2031 return RESULT_SHOWUSAGE
;
2033 for(i
= 0 ; i
< MAX_STAT_LINKS
; i
++)
2034 listoflinks
[i
] = NULL
;
2036 tot_state
= ider_state
=
2037 patch_state
= reverse_patch_state
=
2038 input_signal
= called_number
=
2039 lastdtmfcommand
= not_applicable
;
2041 for(i
= 0; i
< nrpts
; i
++)
2043 if (!strcmp(argv
[2],rpt_vars
[i
].name
)){
2044 /* Make a copy of all stat variables while locked */
2045 myrpt
= &rpt_vars
[i
];
2046 rpt_mutex_lock(&myrpt
->lock
); /* LOCK */
2048 dailytxtime
= myrpt
->dailytxtime
;
2049 totaltxtime
= myrpt
->totaltxtime
;
2050 dailykeyups
= myrpt
->dailykeyups
;
2051 totalkeyups
= myrpt
->totalkeyups
;
2052 dailykerchunks
= myrpt
->dailykerchunks
;
2053 totalkerchunks
= myrpt
->totalkerchunks
;
2054 dailyexecdcommands
= myrpt
->dailyexecdcommands
;
2055 totalexecdcommands
= myrpt
->totalexecdcommands
;
2056 timeouts
= myrpt
->timeouts
;
2058 /* Traverse the list of connected nodes */
2059 reverse_patch_state
= "DOWN";
2061 l
= myrpt
->links
.next
;
2062 while(l
&& (l
!= &myrpt
->links
)){
2063 if (l
->name
[0] == '0'){ /* Skip '0' nodes */
2064 reverse_patch_state
= "UP";
2068 listoflinks
[j
] = ast_strdupa(l
->name
);
2074 lastnodewhichkeyedusup
= ast_strdupa(myrpt
->lastnodewhichkeyedusup
);
2075 if((!lastnodewhichkeyedusup
) || (!strlen(lastnodewhichkeyedusup
)))
2076 lastnodewhichkeyedusup
= not_applicable
;
2079 input_signal
= "YES";
2081 input_signal
= "NO";
2083 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
)
2084 sys_ena
= "DISABLED";
2086 sys_ena
= "ENABLED";
2088 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].totdisable
)
2089 tot_ena
= "DISABLED";
2091 tot_ena
= "ENABLED";
2093 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].linkfundisable
)
2094 link_ena
= "DISABLED";
2096 link_ena
= "ENABLED";
2098 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].autopatchdisable
)
2099 patch_ena
= "DISABLED";
2101 patch_ena
= "ENABLED";
2103 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].schedulerdisable
)
2104 sch_ena
= "DISABLED";
2106 sch_ena
= "ENABLED";
2108 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].userfundisable
)
2109 user_funs
= "DISABLED";
2111 user_funs
= "ENABLED";
2113 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].alternatetail
)
2114 tail_type
= "ALTERNATE";
2116 tail_type
= "STANDARD";
2119 tot_state
= "TIMED OUT!";
2120 else if(myrpt
->totimer
!= myrpt
->p
.totime
)
2121 tot_state
= "ARMED";
2123 tot_state
= "RESET";
2126 ider_state
= "QUEUED IN TAIL";
2127 else if(myrpt
->mustid
)
2128 ider_state
= "QUEUED FOR CLEANUP";
2130 ider_state
= "CLEAN";
2132 switch(myrpt
->callmode
){
2134 patch_state
= "DIALING";
2137 patch_state
= "CONNECTING";
2144 patch_state
= "CALL FAILED";
2148 patch_state
= "DOWN";
2151 if(strlen(myrpt
->exten
)){
2152 called_number
= ast_strdupa(myrpt
->exten
);
2154 called_number
= not_applicable
;
2157 if(strlen(myrpt
->lastdtmfcommand
)){
2158 lastdtmfcommand
= ast_strdupa(myrpt
->lastdtmfcommand
);
2159 if(!lastdtmfcommand
)
2160 lastdtmfcommand
= not_applicable
;
2163 rpt_mutex_unlock(&myrpt
->lock
); /* UNLOCK */
2165 ast_cli(fd
, "************************ NODE %s STATISTICS *************************\n\n", myrpt
->name
);
2166 ast_cli(fd
, "Selected system state............................: %d\n", myrpt
->p
.sysstate_cur
);
2167 ast_cli(fd
, "Signal on input..................................: %s\n", input_signal
);
2168 ast_cli(fd
, "System...........................................: %s\n", sys_ena
);
2169 ast_cli(fd
, "Scheduler........................................: %s\n", sch_ena
);
2170 ast_cli(fd
, "Tail Time........................................: %s\n", tail_type
);
2171 ast_cli(fd
, "Time out timer...................................: %s\n", tot_ena
);
2172 ast_cli(fd
, "Time out timer state.............................: %s\n", tot_state
);
2173 ast_cli(fd
, "Time outs since system initialization............: %d\n", timeouts
);
2174 ast_cli(fd
, "Identifier state.................................: %s\n", ider_state
);
2175 ast_cli(fd
, "Kerchunks today..................................: %d\n", dailykerchunks
);
2176 ast_cli(fd
, "Kerchunks since system initialization............: %d\n", totalkerchunks
);
2177 ast_cli(fd
, "Keyups today.....................................: %d\n", dailykeyups
);
2178 ast_cli(fd
, "Keyups since system initialization...............: %d\n", totalkeyups
);
2179 ast_cli(fd
, "DTMF commands today..............................: %d\n", dailyexecdcommands
);
2180 ast_cli(fd
, "DTMF commands since system initialization........: %d\n", totalexecdcommands
);
2181 ast_cli(fd
, "Last DTMF command executed.......................: %s\n", lastdtmfcommand
);
2182 hours
= dailytxtime
/3600000;
2183 dailytxtime
%= 3600000;
2184 minutes
= dailytxtime
/60000;
2185 dailytxtime
%= 60000;
2186 seconds
= dailytxtime
/1000;
2187 dailytxtime
%= 1000;
2189 ast_cli(fd
, "TX time today ...................................: %02d:%02d:%02d.%d\n",
2190 hours
, minutes
, seconds
, dailytxtime
);
2192 hours
= (int) totaltxtime
/3600000;
2193 totaltxtime
%= 3600000;
2194 minutes
= (int) totaltxtime
/60000;
2195 totaltxtime
%= 60000;
2196 seconds
= (int) totaltxtime
/1000;
2197 totaltxtime
%= 1000;
2199 ast_cli(fd
, "TX time since system initialization..............: %02d:%02d:%02d.%d\n",
2200 hours
, minutes
, seconds
, (int) totaltxtime
);
2201 ast_cli(fd
, "Nodes currently connected to us..................: ");
2203 if(!listoflinks
[j
]){
2205 ast_cli(fd
,"<NONE>");
2209 ast_cli(fd
, "%s", listoflinks
[j
]);
2215 if(listoflinks
[j
+ 1])
2221 ast_cli(fd
, "Last node which transmitted to us................: %s\n", lastnodewhichkeyedusup
);
2222 ast_cli(fd
, "Autopatch........................................: %s\n", patch_ena
);
2223 ast_cli(fd
, "Autopatch state..................................: %s\n", patch_state
);
2224 ast_cli(fd
, "Autopatch called number..........................: %s\n", called_number
);
2225 ast_cli(fd
, "Reverse patch/IAXRPT connected...................: %s\n", reverse_patch_state
);
2226 ast_cli(fd
, "User linking commands............................: %s\n", link_ena
);
2227 ast_cli(fd
, "User functions...................................: %s\n\n", user_funs
);
2228 return RESULT_SUCCESS
;
2231 return RESULT_FAILURE
;
2235 * Link stats function
2238 static int rpt_do_lstats(int fd
, int argc
, char *argv
[])
2244 struct rpt_lstat
*s
,*t
;
2245 struct rpt_lstat s_head
;
2247 return RESULT_SHOWUSAGE
;
2250 s_head
.next
= &s_head
;
2251 s_head
.prev
= &s_head
;
2253 for(i
= 0; i
< nrpts
; i
++)
2255 if (!strcmp(argv
[2],rpt_vars
[i
].name
)){
2256 /* Make a copy of all stat variables while locked */
2257 myrpt
= &rpt_vars
[i
];
2258 rpt_mutex_lock(&myrpt
->lock
); /* LOCK */
2259 /* Traverse the list of connected nodes */
2261 l
= myrpt
->links
.next
;
2262 while(l
&& (l
!= &myrpt
->links
)){
2263 if (l
->name
[0] == '0'){ /* Skip '0' nodes */
2267 if((s
= (struct rpt_lstat
*) malloc(sizeof(struct rpt_lstat
))) == NULL
){
2268 ast_log(LOG_ERROR
, "Malloc failed in rpt_do_lstats\n");
2269 rpt_mutex_unlock(&myrpt
->lock
); /* UNLOCK */
2270 return RESULT_FAILURE
;
2272 memset(s
, 0, sizeof(struct rpt_lstat
));
2273 strncpy(s
->name
, l
->name
, MAXREMSTR
- 1);
2274 if (l
->chan
) pbx_substitute_variables_helper(l
->chan
, "${IAXPEER(CURRENTCHANNEL)}", s
->peer
, MAXPEERSTR
- 1);
2275 else strcpy(s
->peer
,"(none)");
2277 s
->outbound
= l
->outbound
;
2278 s
->reconnects
= l
->reconnects
;
2279 s
->connecttime
= l
->connecttime
;
2280 s
->thisconnected
= l
->thisconnected
;
2281 memcpy(s
->chan_stat
,l
->chan_stat
,NRPTSTAT
* sizeof(struct rpt_chan_stat
));
2282 insque((struct qelem
*) s
, (struct qelem
*) s_head
.next
);
2283 memset(l
->chan_stat
,0,NRPTSTAT
* sizeof(struct rpt_chan_stat
));
2286 rpt_mutex_unlock(&myrpt
->lock
); /* UNLOCK */
2287 ast_cli(fd
, "NODE PEER RECONNECTS DIRECTION CONNECT TIME CONNECT STATE\n");
2288 ast_cli(fd
, "---- ---- ---------- --------- ------------ -------------\n");
2290 for(s
= s_head
.next
; s
!= &s_head
; s
= s
->next
){
2291 int hours
, minutes
, seconds
;
2292 long long connecttime
= s
->connecttime
;
2294 hours
= (int) connecttime
/3600000;
2295 connecttime
%= 3600000;
2296 minutes
= (int) connecttime
/60000;
2297 connecttime
%= 60000;
2298 seconds
= (int) connecttime
/1000;
2299 connecttime
%= 1000;
2300 snprintf(conntime
, 20, "%02d:%02d:%02d.%d",
2301 hours
, minutes
, seconds
, (int) connecttime
);
2303 if(s
->thisconnected
)
2304 connstate
= "ESTABLISHED";
2306 connstate
= "CONNECTING";
2307 ast_cli(fd
, "%-10s%-20s%-12d%-11s%-20s%-20s\n",
2308 s
->name
, s
->peer
, s
->reconnects
, (s
->outbound
)? "OUT":"IN", conntime
, connstate
);
2310 /* destroy our local link queue */
2312 while(s
!= &s_head
){
2315 remque((struct qelem
*)t
);
2318 return RESULT_SUCCESS
;
2321 return RESULT_FAILURE
;
2325 * List all nodes connected, directly or indirectly
2328 static int rpt_do_nodes(int fd
, int argc
, char *argv
[])
2332 char lbuf
[MAXLINKLIST
],*strs
[MAXLINKLIST
];
2335 return RESULT_SHOWUSAGE
;
2337 for(i
= 0; i
< nrpts
; i
++)
2339 if (!strcmp(argv
[2],rpt_vars
[i
].name
)){
2340 /* Make a copy of all stat variables while locked */
2341 myrpt
= &rpt_vars
[i
];
2342 rpt_mutex_lock(&myrpt
->lock
); /* LOCK */
2343 __mklinklist(myrpt
,NULL
,lbuf
);
2344 rpt_mutex_unlock(&myrpt
->lock
); /* UNLOCK */
2346 ns
= finddelim(lbuf
,strs
,MAXLINKLIST
);
2348 if (ns
) qsort((void *)strs
,ns
,sizeof(char *),mycompar
);
2350 ast_cli(fd
, "************************* CONNECTED NODES *************************\n\n");
2354 ast_cli(fd
,"<NONE>");
2358 ast_cli(fd
, "%s", strs
[j
]);
2368 return RESULT_SUCCESS
;
2371 return RESULT_FAILURE
;
2378 static int rpt_do_reload(int fd
, int argc
, char *argv
[])
2382 if (argc
> 2) return RESULT_SHOWUSAGE
;
2384 for(n
= 0; n
< nrpts
; n
++) rpt_vars
[n
].reload
= 1;
2386 return RESULT_FAILURE
;
2393 static int rpt_do_restart(int fd
, int argc
, char *argv
[])
2397 if (argc
> 2) return RESULT_SHOWUSAGE
;
2398 for(i
= 0; i
< nrpts
; i
++)
2400 if (rpt_vars
[i
].rxchannel
) ast_softhangup(rpt_vars
[i
].rxchannel
,AST_SOFTHANGUP_DEV
);
2402 return RESULT_FAILURE
;
2407 * send an app_rpt DTMF function from the CLI
2410 static int rpt_do_fun(int fd
, int argc
, char *argv
[])
2414 if (argc
!= 4) return RESULT_SHOWUSAGE
;
2416 for(i
= 0; i
< nrpts
; i
++){
2417 if(!strcmp(argv
[2], rpt_vars
[i
].name
)){
2418 struct rpt
*myrpt
= &rpt_vars
[i
];
2419 rpt_mutex_lock(&myrpt
->lock
);
2420 if ((MAXMACRO
- strlen(myrpt
->macrobuf
)) < strlen(argv
[3])){
2421 rpt_mutex_unlock(&myrpt
->lock
);
2425 myrpt
->macrotimer
= MACROTIME
;
2426 strncat(myrpt
->macrobuf
, argv
[3], MAXMACRO
- strlen(myrpt
->macrobuf
) - 1);
2428 rpt_mutex_unlock(&myrpt
->lock
);
2432 ast_cli(fd
, "Function decoder busy");
2434 return RESULT_FAILURE
;
2439 static int play_tone_pair(struct ast_channel
*chan
, int f1
, int f2
, int duration
, int amplitude
)
2443 if ((res
= ast_tonepair_start(chan
, f1
, f2
, duration
, amplitude
)))
2446 while(chan
->generatordata
) {
2447 if (ast_safe_sleep(chan
,1)) return -1;
2453 static int play_tone(struct ast_channel
*chan
, int freq
, int duration
, int amplitude
)
2455 return play_tone_pair(chan
, freq
, 0, duration
, amplitude
);
2458 static int play_silence(struct ast_channel
*chan
, int duration
)
2460 return play_tone_pair(chan
, 0, 0, duration
, 0);
2464 static int send_morse(struct ast_channel
*chan
, char *string
, int speed
, int freq
, int amplitude
)
2467 static struct morse_bits mbits
[] = {
2532 int intralettertime
;
2533 int interlettertime
;
2543 /* Approximate the dot time from the speed arg. */
2545 dottime
= 900/speed
;
2547 /* Establish timing releationships */
2549 dashtime
= 3 * dottime
;
2550 intralettertime
= dottime
;
2551 interlettertime
= dottime
* 4 ;
2552 interwordtime
= dottime
* 7;
2554 for(;(*string
) && (!res
); string
++){
2558 /* Convert lower case to upper case */
2560 if((c
>= 'a') && (c
<= 'z'))
2563 /* Can't deal with any char code greater than Z, skip it */
2568 /* If space char, wait the inter word time */
2572 res
= play_silence(chan
, interwordtime
);
2576 /* Subtract out control char offset to match our table */
2580 /* Get the character data */
2583 ddcomb
= mbits
[c
].ddcomb
;
2585 /* Send the character */
2589 res
= play_tone(chan
, freq
, (ddcomb
& 1) ? dashtime
: dottime
, amplitude
);
2591 res
= play_silence(chan
, intralettertime
);
2595 /* Wait the interletter time */
2598 res
= play_silence(chan
, interlettertime
- intralettertime
);
2601 /* Wait for all the frames to be sent */
2604 res
= ast_waitstream(chan
, "");
2605 ast_stopstream(chan
);
2608 * Wait for the zaptel driver to physically write the tone blocks to the hardware
2611 for(i
= 0; i
< 20 ; i
++){
2612 flags
= ZT_IOMUX_WRITEEMPTY
| ZT_IOMUX_NOWAIT
;
2613 res
= ioctl(chan
->fds
[0], ZT_IOMUX
, &flags
);
2614 if(flags
& ZT_IOMUX_WRITEEMPTY
)
2616 if( ast_safe_sleep(chan
, 50)){
2626 static int send_tone_telemetry(struct ast_channel
*chan
, char *tonestring
)
2639 stringp
= ast_strdupa(tonestring
);
2642 tonesubset
= strsep(&stringp
,")");
2645 if(sscanf(tonesubset
,"(%d,%d,%d,%d", &f1
, &f2
, &duration
, &litude
) != 4)
2647 res
= play_tone_pair(chan
, f1
, f2
, duration
, amplitude
);
2652 res
= play_tone_pair(chan
, 0, 0, 100, 0); /* This is needed to ensure the last tone segment is timed correctly */
2655 res
= ast_waitstream(chan
, "");
2656 ast_stopstream(chan
);
2659 * Wait for the zaptel driver to physically write the tone blocks to the hardware
2662 for(i
= 0; i
< 20 ; i
++){
2663 flags
= ZT_IOMUX_WRITEEMPTY
| ZT_IOMUX_NOWAIT
;
2664 res
= ioctl(chan
->fds
[0], ZT_IOMUX
, &flags
);
2665 if(flags
& ZT_IOMUX_WRITEEMPTY
)
2667 if( ast_safe_sleep(chan
, 50)){
2677 static int sayfile(struct ast_channel
*mychannel
,char *fname
)
2681 res
= ast_streamfile(mychannel
, fname
, mychannel
->language
);
2683 res
= ast_waitstream(mychannel
, "");
2685 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
2686 ast_stopstream(mychannel
);
2690 static int saycharstr(struct ast_channel
*mychannel
,char *str
)
2694 res
= ast_say_character_str(mychannel
,str
,NULL
,mychannel
->language
);
2696 res
= ast_waitstream(mychannel
, "");
2698 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
2699 ast_stopstream(mychannel
);
2703 static int saynum(struct ast_channel
*mychannel
, int num
)
2706 res
= ast_say_number(mychannel
, num
, NULL
, mychannel
->language
, NULL
);
2708 res
= ast_waitstream(mychannel
, "");
2710 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
2711 ast_stopstream(mychannel
);
2716 static int telem_any(struct rpt
*myrpt
,struct ast_channel
*chan
, char *entry
)
2721 static int morsespeed
;
2722 static int morsefreq
;
2723 static int morseampl
;
2724 static int morseidfreq
= 0;
2725 static int morseidampl
;
2726 static char mcat
[] = MORSE
;
2730 if(!morseidfreq
){ /* Get the morse parameters if not already loaded */
2731 morsespeed
= retrieve_astcfgint(myrpt
, mcat
, "speed", 5, 20, 20);
2732 morsefreq
= retrieve_astcfgint(myrpt
, mcat
, "frequency", 300, 3000, 800);
2733 morseampl
= retrieve_astcfgint(myrpt
, mcat
, "amplitude", 200, 8192, 4096);
2734 morseidampl
= retrieve_astcfgint(myrpt
, mcat
, "idamplitude", 200, 8192, 2048);
2735 morseidfreq
= retrieve_astcfgint(myrpt
, mcat
, "idfrequency", 300, 3000, 330);
2738 /* Is it a file, or a tone sequence? */
2740 if(entry
[0] == '|'){
2742 if((c
>= 'a')&&(c
<= 'z'))
2746 case 'I': /* Morse ID */
2747 res
= send_morse(chan
, entry
+ 2, morsespeed
, morseidfreq
, morseidampl
);
2750 case 'M': /* Morse Message */
2751 res
= send_morse(chan
, entry
+ 2, morsespeed
, morsefreq
, morseampl
);
2754 case 'T': /* Tone sequence */
2755 res
= send_tone_telemetry(chan
, entry
+ 2);
2762 res
= sayfile(chan
, entry
); /* File */
2767 * This function looks up a telemetry name in the config file, and does a telemetry response as configured.
2769 * 4 types of telemtry are handled: Morse ID, Morse Message, Tone Sequence, and a File containing a recording.
2772 static int telem_lookup(struct rpt
*myrpt
,struct ast_channel
*chan
, char *node
, char *name
)
2779 char *telemetry_save
;
2782 telemetry_save
= NULL
;
2785 /* Retrieve the section name for telemetry from the node section */
2786 telemetry
= (char *) ast_variable_retrieve(myrpt
->cfg
, node
, TELEMETRY
);
2788 telemetry_save
= ast_strdupa(telemetry
);
2789 if(!telemetry_save
){
2790 ast_log(LOG_WARNING
,"ast_strdupa() failed in telem_lookup()\n");
2793 entry
= (char *) ast_variable_retrieve(myrpt
->cfg
, telemetry_save
, name
);
2796 /* Try to look up the telemetry name */
2799 /* Telemetry name wasn't found in the config file, use the default */
2800 for(i
= 0; i
< sizeof(tele_defs
)/sizeof(struct telem_defaults
) ; i
++){
2801 if(!strcasecmp(tele_defs
[i
].name
, name
))
2802 entry
= tele_defs
[i
].value
;
2807 telem_any(myrpt
,chan
, entry
);
2816 * Retrieve a wait interval
2819 static int get_wait_interval(struct rpt
*myrpt
, int type
)
2823 char *wait_times_save
;
2825 wait_times_save
= NULL
;
2826 wait_times
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->name
, "wait_times");
2829 wait_times_save
= ast_strdupa(wait_times
);
2830 if(!wait_times_save
){
2831 ast_log(LOG_WARNING
, "Out of memory in wait_interval()\n");
2839 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "telemwait", 500, 5000, 1000);
2846 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "idwait",250,5000,500);
2853 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "unkeywait",500,5000,1000);
2860 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "linkunkeywait",500,5000,1000);
2867 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "calltermwait",500,5000,1500);
2874 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "compwait",500,5000,200);
2887 * Wait a configurable interval of time
2891 static void wait_interval(struct rpt
*myrpt
, int type
, struct ast_channel
*chan
)
2894 interval
= get_wait_interval(myrpt
, type
);
2896 ast_log(LOG_NOTICE
," Delay interval = %d\n", interval
);
2898 ast_safe_sleep(chan
,interval
);
2900 ast_log(LOG_NOTICE
,"Delay complete\n");
2904 static int split_freq(char *mhz
, char *decimals
, char *freq
);
2906 static void *rpt_tele_thread(void *this)
2908 ZT_CONFINFO ci
; /* conference info */
2909 int res
= 0,haslink
,hastx
,hasremote
,imdone
= 0, unkeys_queued
, x
;
2910 struct rpt_tele
*mytele
= (struct rpt_tele
*)this;
2911 struct rpt_tele
*tlist
;
2913 struct rpt_link
*l
,*l1
,linkbase
;
2914 struct ast_channel
*mychannel
;
2915 int vmajor
, vminor
, m
;
2916 char *p
,*ct
,*ct_copy
,*ident
, *nodename
,*cp
;
2919 char lbuf
[MAXLINKLIST
],*strs
[MAXLINKLIST
];
2921 char mhz
[MAXREMSTR
];
2922 char decimals
[MAXREMSTR
];
2923 struct zt_params par
;
2926 /* get a pointer to myrpt */
2927 myrpt
= mytele
->rpt
;
2929 /* Snag copies of a few key myrpt variables */
2930 rpt_mutex_lock(&myrpt
->lock
);
2931 nodename
= ast_strdupa(myrpt
->name
);
2932 if (myrpt
->p
.ident
) ident
= ast_strdupa(myrpt
->p
.ident
);
2934 rpt_mutex_unlock(&myrpt
->lock
);
2936 /* allocate a pseudo-channel thru asterisk */
2937 mychannel
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
2940 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
2941 rpt_mutex_lock(&myrpt
->lock
);
2942 remque((struct qelem
*)mytele
);
2943 ast_log(LOG_NOTICE
,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__
, mytele
->mode
); /*@@@@@@@@@@@*/
2944 rpt_mutex_unlock(&myrpt
->lock
);
2948 #ifdef AST_CDR_FLAG_POST_DISABLED
2949 ast_set_flag(mychannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
2951 rpt_mutex_lock(&myrpt
->lock
);
2952 mytele
->chan
= mychannel
;
2953 rpt_mutex_unlock(&myrpt
->lock
);
2954 /* make a conference for the tx */
2956 /* If there's an ID queued, or tail message queued, */
2957 /* only connect the ID audio to the local tx conference so */
2958 /* linked systems can't hear it */
2959 ci
.confno
= (((mytele
->mode
== ID
) || (mytele
->mode
== IDTALKOVER
) || (mytele
->mode
== UNKEY
) ||
2960 (mytele
->mode
== TAILMSG
) || (mytele
->mode
== LINKUNKEY
)) || (mytele
->mode
== TIMEOUT
) ?
2961 myrpt
->txconf
: myrpt
->conf
);
2962 ci
.confmode
= ZT_CONF_CONFANN
;
2963 /* first put the channel on the conference in announce mode */
2964 if (ioctl(mychannel
->fds
[0],ZT_SETCONF
,&ci
) == -1)
2966 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
2967 rpt_mutex_lock(&myrpt
->lock
);
2968 remque((struct qelem
*)mytele
);
2969 rpt_mutex_unlock(&myrpt
->lock
);
2970 ast_log(LOG_NOTICE
,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__
, mytele
->mode
); /*@@@@@@@@@@@*/
2972 ast_hangup(mychannel
);
2975 ast_stopstream(mychannel
);
2976 switch(mytele
->mode
)
2981 wait_interval(myrpt
, (mytele
->mode
== ID
) ? DLY_ID
: DLY_TELEM
,mychannel
);
2982 res
= telem_any(myrpt
,mychannel
, ident
);
2987 res
= ast_streamfile(mychannel
, myrpt
->p
.tailmessages
[myrpt
->tailmessagen
], mychannel
->language
);
2991 p
= (char *) ast_variable_retrieve(myrpt
->cfg
, nodename
, "idtalkover");
2993 res
= telem_any(myrpt
,mychannel
, p
);
2998 /* wait a little bit longer */
2999 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3000 res
= telem_lookup(myrpt
, mychannel
, myrpt
->name
, "patchup");
3001 if(res
< 0){ /* Then default message */
3002 res
= ast_streamfile(mychannel
, "rpt/callproceeding", mychannel
->language
);
3006 /* wait a little bit longer */
3007 wait_interval(myrpt
, DLY_CALLTERM
, mychannel
);
3008 res
= telem_lookup(myrpt
, mychannel
, myrpt
->name
, "patchdown");
3009 if(res
< 0){ /* Then default message */
3010 res
= ast_streamfile(mychannel
, "rpt/callterminated", mychannel
->language
);
3014 /* wait a little bit */
3015 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3016 res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "functcomplete");
3018 case MACRO_NOTFOUND
:
3019 /* wait a little bit */
3020 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3021 res
= ast_streamfile(mychannel
, "rpt/macro_notfound", mychannel
->language
);
3024 /* wait a little bit */
3025 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3026 res
= ast_streamfile(mychannel
, "rpt/macro_busy", mychannel
->language
);
3029 if(myrpt
->patchnoct
&& myrpt
->callmode
){ /* If no CT during patch configured, then don't send one */
3035 * Reset the Unkey to CT timer
3038 x
= get_wait_interval(myrpt
, DLY_UNKEY
);
3039 rpt_mutex_lock(&myrpt
->lock
);
3040 myrpt
->unkeytocttimer
= x
; /* Must be protected as it is changed below */
3041 rpt_mutex_unlock(&myrpt
->lock
);
3044 * If there's one already queued, don't do another
3047 tlist
= myrpt
->tele
.next
;
3049 if (tlist
!= &myrpt
->tele
)
3051 rpt_mutex_lock(&myrpt
->lock
);
3052 while(tlist
!= &myrpt
->tele
){
3053 if (tlist
->mode
== UNKEY
) unkeys_queued
++;
3054 tlist
= tlist
->next
;
3056 rpt_mutex_unlock(&myrpt
->lock
);
3058 if( unkeys_queued
> 1){
3063 /* Wait for the telemetry timer to expire */
3064 /* Periodically check the timer since it can be re-initialized above */
3065 while(myrpt
->unkeytocttimer
)
3068 if(myrpt
->unkeytocttimer
> 100)
3071 ctint
= myrpt
->unkeytocttimer
;
3072 ast_safe_sleep(mychannel
, ctint
);
3073 rpt_mutex_lock(&myrpt
->lock
);
3074 if(myrpt
->unkeytocttimer
< ctint
)
3075 myrpt
->unkeytocttimer
= 0;
3077 myrpt
->unkeytocttimer
-= ctint
;
3078 rpt_mutex_unlock(&myrpt
->lock
);
3082 * Now, the carrier on the rptr rx should be gone.
3083 * If it re-appeared, then forget about sending the CT
3090 rpt_mutex_lock(&myrpt
->lock
); /* Update the kerchunk counters */
3091 myrpt
->dailykerchunks
++;
3092 myrpt
->totalkerchunks
++;
3093 rpt_mutex_unlock(&myrpt
->lock
);
3098 l
= myrpt
->links
.next
;
3099 if (l
!= &myrpt
->links
)
3101 rpt_mutex_lock(&myrpt
->lock
);
3102 while(l
!= &myrpt
->links
)
3104 if (l
->name
[0] == '0')
3112 if (l
->isremote
) hasremote
++;
3116 rpt_mutex_unlock(&myrpt
->lock
);
3121 res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, (!hastx
) ? "remotemon" : "remotetx");
3123 ast_log(LOG_WARNING
, "telem_lookup:remotexx failed on %s\n", mychannel
->name
);
3126 /* if in remote cmd mode, indicate it */
3127 if (myrpt
->cmdnode
[0])
3129 ast_safe_sleep(mychannel
,200);
3130 res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "cmdmode");
3132 ast_log(LOG_WARNING
, "telem_lookup:cmdmode failed on %s\n", mychannel
->name
);
3133 ast_stopstream(mychannel
);
3136 else if((ct
= (char *) ast_variable_retrieve(myrpt
->cfg
, nodename
, "unlinkedct"))){ /* Unlinked Courtesy Tone */
3137 ct_copy
= ast_strdupa(ct
);
3138 res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, ct_copy
);
3140 ast_log(LOG_WARNING
, "telem_lookup:ctx failed on %s\n", mychannel
->name
);
3142 if (hasremote
&& (!myrpt
->cmdnode
[0]))
3144 /* set for all to hear */
3146 ci
.confno
= myrpt
->conf
;
3147 ci
.confmode
= ZT_CONF_CONFANN
;
3148 /* first put the channel on the conference in announce mode */
3149 if (ioctl(mychannel
->fds
[0],ZT_SETCONF
,&ci
) == -1)
3151 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
3152 rpt_mutex_lock(&myrpt
->lock
);
3153 remque((struct qelem
*)mytele
);
3154 rpt_mutex_unlock(&myrpt
->lock
);
3155 ast_log(LOG_NOTICE
,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__
, mytele
->mode
); /*@@@@@@@@@@@*/
3157 ast_hangup(mychannel
);
3160 if((ct
= (char *) ast_variable_retrieve(myrpt
->cfg
, nodename
, "remotect"))){ /* Unlinked Courtesy Tone */
3161 ast_safe_sleep(mychannel
,200);
3162 ct_copy
= ast_strdupa(ct
);
3163 res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, ct_copy
);
3165 ast_log(LOG_WARNING
, "telem_lookup:ctx failed on %s\n", mychannel
->name
);
3168 #if defined(_MDC_DECODE_H_) && defined(MDC_SAY_WHEN_DOING_CT)
3169 if (myrpt
->lastunit
)
3173 ast_safe_sleep(mychannel
,200);
3174 /* set for all to hear */
3176 ci
.confno
= myrpt
->txconf
;
3177 ci
.confmode
= ZT_CONF_CONFANN
;
3178 /* first put the channel on the conference in announce mode */
3179 if (ioctl(mychannel
->fds
[0],ZT_SETCONF
,&ci
) == -1)
3181 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
3182 rpt_mutex_lock(&myrpt
->lock
);
3183 remque((struct qelem
*)mytele
);
3184 rpt_mutex_unlock(&myrpt
->lock
);
3185 ast_log(LOG_NOTICE
,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__
, mytele
->mode
); /*@@@@@@@@@@@*/
3187 ast_hangup(mychannel
);
3190 sprintf(mystr
,"%04x",myrpt
->lastunit
);
3191 myrpt
->lastunit
= 0;
3192 ast_say_character_str(mychannel
,mystr
,NULL
,mychannel
->language
);
3199 if(myrpt
->patchnoct
&& myrpt
->callmode
){ /* If no CT during patch configured, then don't send one */
3205 * Reset the Unkey to CT timer
3208 x
= get_wait_interval(myrpt
, DLY_LINKUNKEY
);
3209 mytele
->mylink
.linkunkeytocttimer
= x
; /* Must be protected as it is changed below */
3212 * If there's one already queued, don't do another
3215 tlist
= myrpt
->tele
.next
;
3217 if (tlist
!= &myrpt
->tele
)
3219 rpt_mutex_lock(&myrpt
->lock
);
3220 while(tlist
!= &myrpt
->tele
){
3221 if (tlist
->mode
== LINKUNKEY
) unkeys_queued
++;
3222 tlist
= tlist
->next
;
3224 rpt_mutex_unlock(&myrpt
->lock
);
3226 if( unkeys_queued
> 1){
3231 /* Wait for the telemetry timer to expire */
3232 /* Periodically check the timer since it can be re-initialized above */
3233 while(mytele
->mylink
.linkunkeytocttimer
)
3236 if(mytele
->mylink
.linkunkeytocttimer
> 100)
3239 ctint
= mytele
->mylink
.linkunkeytocttimer
;
3240 ast_safe_sleep(mychannel
, ctint
);
3241 rpt_mutex_lock(&myrpt
->lock
);
3242 if(mytele
->mylink
.linkunkeytocttimer
< ctint
)
3243 mytele
->mylink
.linkunkeytocttimer
= 0;
3245 mytele
->mylink
.linkunkeytocttimer
-= ctint
;
3246 rpt_mutex_unlock(&myrpt
->lock
);
3249 if((ct
= (char *) ast_variable_retrieve(myrpt
->cfg
, nodename
, "linkunkeyct"))){ /* Unlinked Courtesy Tone */
3250 ct_copy
= ast_strdupa(ct
);
3251 res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, ct_copy
);
3253 ast_log(LOG_WARNING
, "telem_lookup:ctx failed on %s\n", mychannel
->name
);
3258 /* wait a little bit */
3259 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3260 l
= myrpt
->links
.next
;
3262 /* dont report if a link for this one still on system */
3263 if (l
!= &myrpt
->links
)
3265 rpt_mutex_lock(&myrpt
->lock
);
3266 while(l
!= &myrpt
->links
)
3268 if (l
->name
[0] == '0')
3273 if (!strcmp(l
->name
,mytele
->mylink
.name
))
3280 rpt_mutex_unlock(&myrpt
->lock
);
3287 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3289 res
= ast_waitstream(mychannel
, "");
3291 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3292 ast_stopstream(mychannel
);
3293 ast_say_character_str(mychannel
,mytele
->mylink
.name
,NULL
,mychannel
->language
);
3294 res
= ast_streamfile(mychannel
, ((mytele
->mylink
.hasconnected
) ?
3295 "rpt/remote_disc" : "rpt/remote_busy"), mychannel
->language
);
3298 /* wait a little bit */
3299 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3300 res
= ast_streamfile(mychannel
, "rpt/remote_already", mychannel
->language
);
3303 /* wait a little bit */
3304 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3305 res
= ast_streamfile(mychannel
, "rpt/remote_notfound", mychannel
->language
);
3308 /* wait a little bit */
3309 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3310 res
= ast_streamfile(mychannel
, "rpt/remote_go", mychannel
->language
);
3313 /* wait a little bit */
3314 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3315 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3317 res
= ast_waitstream(mychannel
, "");
3319 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3320 ast_stopstream(mychannel
);
3321 ast_say_character_str(mychannel
,mytele
->mylink
.name
,NULL
,mychannel
->language
);
3322 res
= ast_streamfile(mychannel
, "rpt/connected", mychannel
->language
);
3324 res
= ast_waitstream(mychannel
, "");
3326 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3327 ast_stopstream(mychannel
);
3328 res
= ast_streamfile(mychannel
, "digits/2", mychannel
->language
);
3330 res
= ast_waitstream(mychannel
, "");
3332 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3333 ast_stopstream(mychannel
);
3334 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3336 res
= ast_waitstream(mychannel
, "");
3338 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3339 ast_stopstream(mychannel
);
3340 ast_say_character_str(mychannel
,myrpt
->name
,NULL
,mychannel
->language
);
3344 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3346 res
= ast_waitstream(mychannel
, "");
3348 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3349 ast_stopstream(mychannel
);
3350 ast_say_character_str(mychannel
,mytele
->mylink
.name
,NULL
,mychannel
->language
);
3351 res
= ast_streamfile(mychannel
, "rpt/connection_failed", mychannel
->language
);
3354 /* wait a little bit */
3355 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3356 res
= ast_streamfile(mychannel
, "rpt/memory_notfound", mychannel
->language
);
3359 ast_mutex_lock(&myrpt
->remlock
);
3361 if(!strcmp(myrpt
->remote
, remote_rig_ft897
))
3363 res
= set_ft897(myrpt
);
3365 if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
3367 res
= set_ic706(myrpt
);
3369 else if(!strcmp(myrpt
->remote
, remote_rig_rbi
))
3371 if (ioperm(myrpt
->p
.iobase
,1,1) == -1)
3373 rpt_mutex_unlock(&myrpt
->lock
);
3374 ast_log(LOG_WARNING
, "Cant get io permission on IO port %x hex\n",myrpt
->p
.iobase
);
3377 else res
= setrbi(myrpt
);
3379 else if(!strcmp(myrpt
->remote
, remote_rig_kenwood
))
3381 res
= setkenwood(myrpt
);
3382 if (ast_safe_sleep(mychannel
,200) == -1)
3384 ast_mutex_unlock(&myrpt
->remlock
);
3389 if (ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_FLUSH
,&i
) == -1)
3391 ast_mutex_unlock(&myrpt
->remlock
);
3392 ast_log(LOG_ERROR
,"Cant flush events");
3396 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_GET_PARAMS
,&par
) == -1)
3398 ast_mutex_unlock(&myrpt
->remlock
);
3399 ast_log(LOG_ERROR
,"Cant get params");
3404 (par
.rxisoffhook
|| (myrpt
->tele
.next
!= &myrpt
->tele
));
3406 ast_mutex_unlock(&myrpt
->remlock
);
3412 /* fall thru to invalid freq */
3414 /* wait a little bit */
3415 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3416 res
= ast_streamfile(mychannel
, "rpt/invalid-freq", mychannel
->language
);
3420 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3421 switch(myrpt
->remmode
)
3424 saycharstr(mychannel
,"FM");
3427 saycharstr(mychannel
,"USB");
3430 saycharstr(mychannel
,"LSB");
3433 saycharstr(mychannel
,"AM");
3436 wait_interval(myrpt
, DLY_COMP
, mychannel
);
3437 if (!res
) res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "functcomplete");
3440 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3441 sayfile(mychannel
,"rpt/login");
3442 saycharstr(mychannel
,myrpt
->name
);
3445 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3446 saycharstr(mychannel
,myrpt
->loginuser
);
3447 sayfile(mychannel
,"rpt/node");
3448 saycharstr(mychannel
,myrpt
->name
);
3449 wait_interval(myrpt
, DLY_COMP
, mychannel
);
3450 if (!res
) res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "functcomplete");
3453 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3455 switch(mytele
->submode
)
3457 case 100: /* RX PL Off */
3458 sayfile(mychannel
, "rpt/rxpl");
3459 sayfile(mychannel
, "rpt/off");
3461 case 101: /* RX PL On */
3462 sayfile(mychannel
, "rpt/rxpl");
3463 sayfile(mychannel
, "rpt/on");
3465 case 102: /* TX PL Off */
3466 sayfile(mychannel
, "rpt/txpl");
3467 sayfile(mychannel
, "rpt/off");
3469 case 103: /* TX PL On */
3470 sayfile(mychannel
, "rpt/txpl");
3471 sayfile(mychannel
, "rpt/on");
3473 case 104: /* Low Power */
3474 sayfile(mychannel
, "rpt/lopwr");
3476 case 105: /* Medium Power */
3477 sayfile(mychannel
, "rpt/medpwr");
3479 case 106: /* Hi Power */
3480 sayfile(mychannel
, "rpt/hipwr");
3482 case 113: /* Scan down slow */
3483 sayfile(mychannel
,"rpt/down");
3484 sayfile(mychannel
, "rpt/slow");
3486 case 114: /* Scan down quick */
3487 sayfile(mychannel
,"rpt/down");
3488 sayfile(mychannel
, "rpt/quick");
3490 case 115: /* Scan down fast */
3491 sayfile(mychannel
,"rpt/down");
3492 sayfile(mychannel
, "rpt/fast");
3494 case 116: /* Scan up slow */
3495 sayfile(mychannel
,"rpt/up");
3496 sayfile(mychannel
, "rpt/slow");
3498 case 117: /* Scan up quick */
3499 sayfile(mychannel
,"rpt/up");
3500 sayfile(mychannel
, "rpt/quick");
3502 case 118: /* Scan up fast */
3503 sayfile(mychannel
,"rpt/up");
3504 sayfile(mychannel
, "rpt/fast");
3509 wait_interval(myrpt
, DLY_COMP
, mychannel
);
3510 if (!res
) res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "functcomplete");
3513 ast_mutex_lock(&myrpt
->remlock
);
3514 if (myrpt
->hfscanstop
)
3516 myrpt
->hfscanstatus
= 0;
3517 myrpt
->hfscanmode
= 0;
3518 myrpt
->hfscanstop
= 0;
3519 mytele
->mode
= SCANSTAT
;
3520 ast_mutex_unlock(&myrpt
->remlock
);
3521 if (ast_safe_sleep(mychannel
,1000) == -1) break;
3522 sayfile(mychannel
, "rpt/stop");
3526 if (myrpt
->hfscanstatus
> -2) service_scan(myrpt
);
3527 i
= myrpt
->hfscanstatus
;
3528 myrpt
->hfscanstatus
= 0;
3529 if (i
) mytele
->mode
= SCANSTAT
;
3530 ast_mutex_unlock(&myrpt
->remlock
);
3531 if (i
< 0) sayfile(mychannel
, "rpt/stop");
3532 else if (i
> 0) saynum(mychannel
,i
);
3536 ast_mutex_lock(&myrpt
->remlock
);
3537 if (!strcmp(myrpt
->remote
,remote_rig_ic706
))
3539 set_mode_ic706(myrpt
, REM_MODE_AM
);
3540 if(play_tone(mychannel
, 800, 6000, 8192) == -1) break;
3541 ast_safe_sleep(mychannel
,500);
3542 set_mode_ic706(myrpt
, myrpt
->remmode
);
3543 myrpt
->tunerequest
= 0;
3544 ast_mutex_unlock(&myrpt
->remlock
);
3548 set_mode_ft897(myrpt
, REM_MODE_AM
);
3549 simple_command_ft897(myrpt
, 8);
3550 if(play_tone(mychannel
, 800, 6000, 8192) == -1) break;
3551 simple_command_ft897(myrpt
, 0x88);
3552 ast_safe_sleep(mychannel
,500);
3553 set_mode_ft897(myrpt
, myrpt
->remmode
);
3554 myrpt
->tunerequest
= 0;
3555 ast_mutex_unlock(&myrpt
->remlock
);
3558 case REMSHORTSTATUS
:
3560 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3561 res
= sayfile(mychannel
,"rpt/node");
3563 res
= saycharstr(mychannel
, myrpt
->name
);
3565 res
= sayfile(mychannel
,"rpt/frequency");
3567 res
= split_freq(mhz
, decimals
, myrpt
->freq
);
3568 if (!multimode_capable(myrpt
)) decimals
[3] = 0;
3572 res
= saynum(mychannel
, m
);
3574 res
= saycharstr(mychannel
, mhz
);
3577 res
= sayfile(mychannel
, "letters/dot");
3579 res
= saycharstr(mychannel
, decimals
);
3582 if(myrpt
->remmode
== REM_MODE_FM
){ /* Mode FM? */
3583 switch(myrpt
->offset
){
3586 res
= sayfile(mychannel
,"rpt/minus");
3590 res
= sayfile(mychannel
,"rpt/simplex");
3594 res
= sayfile(mychannel
,"rpt/plus");
3601 else{ /* Must be USB, LSB, or AM */
3602 switch(myrpt
->remmode
){
3605 res
= saycharstr(mychannel
, "USB");
3609 res
= saycharstr(mychannel
, "LSB");
3613 res
= saycharstr(mychannel
, "AM");
3622 if (res
== -1) break;
3624 if(mytele
->mode
== REMSHORTSTATUS
){ /* Short status? */
3625 wait_interval(myrpt
, DLY_COMP
, mychannel
);
3626 if (!res
) res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "functcomplete");
3630 if (strcmp(myrpt
->remote
,remote_rig_ic706
))
3632 switch(myrpt
->powerlevel
){
3635 res
= sayfile(mychannel
,"rpt/lopwr") ;
3638 res
= sayfile(mychannel
,"rpt/medpwr");
3641 res
= sayfile(mychannel
,"rpt/hipwr");
3646 rbimode
= ((!strncmp(myrpt
->remote
,remote_rig_rbi
,3))
3647 || (!strncmp(myrpt
->remote
,remote_rig_ic706
,3)));
3648 if (res
|| (sayfile(mychannel
,"rpt/rxpl") == -1)) break;
3649 if (rbimode
&& (sayfile(mychannel
,"rpt/txpl") == -1)) break;
3650 if ((sayfile(mychannel
,"rpt/frequency") == -1) ||
3651 (saycharstr(mychannel
,myrpt
->rxpl
) == -1)) break;
3652 if ((!rbimode
) && ((sayfile(mychannel
,"rpt/txpl") == -1) ||
3653 (sayfile(mychannel
,"rpt/frequency") == -1) ||
3654 (saycharstr(mychannel
,myrpt
->txpl
) == -1))) break;
3655 if(myrpt
->remmode
== REM_MODE_FM
){ /* Mode FM? */
3656 if ((sayfile(mychannel
,"rpt/rxpl") == -1) ||
3657 (sayfile(mychannel
,((myrpt
->rxplon
) ? "rpt/on" : "rpt/off")) == -1) ||
3658 (sayfile(mychannel
,"rpt/txpl") == -1) ||
3659 (sayfile(mychannel
,((myrpt
->txplon
) ? "rpt/on" : "rpt/off")) == -1))
3664 wait_interval(myrpt
, DLY_COMP
, mychannel
);
3665 if (!res
) res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "functcomplete");
3668 /* wait a little bit */
3669 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3671 linkbase
.next
= &linkbase
;
3672 linkbase
.prev
= &linkbase
;
3673 rpt_mutex_lock(&myrpt
->lock
);
3674 /* make our own list of links */
3675 l
= myrpt
->links
.next
;
3676 while(l
!= &myrpt
->links
)
3678 if (l
->name
[0] == '0')
3683 l1
= malloc(sizeof(struct rpt_link
));
3686 ast_log(LOG_WARNING
, "Cannot alloc memory on %s\n", mychannel
->name
);
3687 remque((struct qelem
*)mytele
);
3688 rpt_mutex_unlock(&myrpt
->lock
);
3689 ast_log(LOG_NOTICE
,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__
, mytele
->mode
); /*@@@@@@@@@@@*/
3691 ast_hangup(mychannel
);
3694 memcpy(l1
,l
,sizeof(struct rpt_link
));
3695 l1
->next
= l1
->prev
= NULL
;
3696 insque((struct qelem
*)l1
,(struct qelem
*)linkbase
.next
);
3699 rpt_mutex_unlock(&myrpt
->lock
);
3700 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3702 res
= ast_waitstream(mychannel
, "");
3704 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3705 ast_stopstream(mychannel
);
3706 ast_say_character_str(mychannel
,myrpt
->name
,NULL
,mychannel
->language
);
3708 res
= ast_waitstream(mychannel
, "");
3710 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3711 ast_stopstream(mychannel
);
3712 if (myrpt
->callmode
)
3715 res
= ast_streamfile(mychannel
, "rpt/autopatch_on", mychannel
->language
);
3717 res
= ast_waitstream(mychannel
, "");
3719 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3720 ast_stopstream(mychannel
);
3723 while(l
!= &linkbase
)
3728 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3730 res
= ast_waitstream(mychannel
, "");
3732 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3733 ast_stopstream(mychannel
);
3734 ast_say_character_str(mychannel
,l
->name
,NULL
,mychannel
->language
);
3736 res
= ast_waitstream(mychannel
, "");
3738 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3739 ast_stopstream(mychannel
);
3740 s
= "rpt/tranceive";
3741 if (!l
->mode
) s
= "rpt/monitor";
3742 if (!l
->thisconnected
) s
= "rpt/connecting";
3743 res
= ast_streamfile(mychannel
, s
, mychannel
->language
);
3745 res
= ast_waitstream(mychannel
, "");
3747 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3748 ast_stopstream(mychannel
);
3753 res
= ast_streamfile(mychannel
, "rpt/repeat_only", mychannel
->language
);
3755 res
= ast_waitstream(mychannel
, "");
3757 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3758 ast_stopstream(mychannel
);
3760 /* destroy our local link queue */
3762 while(l
!= &linkbase
)
3766 remque((struct qelem
*)l1
);
3772 rpt_mutex_lock(&myrpt
->lock
);
3773 /* get all the nodes */
3774 __mklinklist(myrpt
,NULL
,lbuf
);
3775 rpt_mutex_unlock(&myrpt
->lock
);
3777 ns
= finddelim(lbuf
,strs
,MAXLINKLIST
);
3779 if (ns
) qsort((void *)strs
,ns
,sizeof(char *),mycompar
);
3780 /* wait a little bit */
3781 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3783 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3785 res
= ast_waitstream(mychannel
, "");
3787 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3788 ast_stopstream(mychannel
);
3789 ast_say_character_str(mychannel
,myrpt
->name
,NULL
,mychannel
->language
);
3791 res
= ast_waitstream(mychannel
, "");
3793 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3794 ast_stopstream(mychannel
);
3795 if (myrpt
->callmode
)
3798 res
= ast_streamfile(mychannel
, "rpt/autopatch_on", mychannel
->language
);
3800 res
= ast_waitstream(mychannel
, "");
3802 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3803 ast_stopstream(mychannel
);
3805 /* go thru all the nodes in list */
3806 for(i
= 0; i
< ns
; i
++)
3810 /* if a mode spec at first, handle it */
3811 if ((*strs
[i
] < '0') || (*strs
[i
] > '9'))
3818 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3820 res
= ast_waitstream(mychannel
, "");
3822 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3823 ast_stopstream(mychannel
);
3824 ast_say_character_str(mychannel
,strs
[i
],NULL
,mychannel
->language
);
3826 res
= ast_waitstream(mychannel
, "");
3828 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3829 ast_stopstream(mychannel
);
3830 s
= "rpt/tranceive";
3831 if (mode
== 'R') s
= "rpt/monitor";
3832 if (mode
== 'C') s
= "rpt/connecting";
3833 res
= ast_streamfile(mychannel
, s
, mychannel
->language
);
3835 res
= ast_waitstream(mychannel
, "");
3837 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3838 ast_stopstream(mychannel
);
3842 res
= ast_streamfile(mychannel
, "rpt/repeat_only", mychannel
->language
);
3844 res
= ast_waitstream(mychannel
, "");
3846 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3847 ast_stopstream(mychannel
);
3852 case LASTNODEKEY
: /* Identify last node which keyed us up */
3853 rpt_mutex_lock(&myrpt
->lock
);
3854 if(myrpt
->lastnodewhichkeyedusup
)
3855 p
= ast_strdupa(myrpt
->lastnodewhichkeyedusup
); /* Make a local copy of the node name */
3858 rpt_mutex_unlock(&myrpt
->lock
);
3860 imdone
= 1; /* no node previously keyed us up, or the node which did has been disconnected */
3863 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3864 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3866 res
= ast_waitstream(mychannel
, "");
3868 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3869 ast_stopstream(mychannel
);
3870 ast_say_character_str(mychannel
, p
, NULL
, mychannel
->language
);
3872 res
= ast_waitstream(mychannel
, "");
3874 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3875 ast_stopstream(mychannel
);
3879 case UNAUTHTX
: /* Say unauthorized transmit frequency */
3880 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3881 res
= ast_streamfile(mychannel
, "rpt/unauthtx", mychannel
->language
);
3883 res
= ast_waitstream(mychannel
, "");
3885 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3886 ast_stopstream(mychannel
);
3892 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3894 res
= ast_waitstream(mychannel
, "");
3896 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3897 ast_stopstream(mychannel
);
3898 ast_say_character_str(mychannel
,myrpt
->name
,NULL
,mychannel
->language
);
3899 res
= ast_streamfile(mychannel
, "rpt/timeout", mychannel
->language
);
3902 case TIMEOUT_WARNING
:
3904 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3906 res
= ast_waitstream(mychannel
, "");
3908 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3909 ast_stopstream(mychannel
);
3910 ast_say_character_str(mychannel
,myrpt
->name
,NULL
,mychannel
->language
);
3911 res
= ast_streamfile(mychannel
, "rpt/timeout-warning", mychannel
->language
);
3913 res
= ast_waitstream(mychannel
, "");
3915 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3916 ast_stopstream(mychannel
);
3917 if(!res
) /* Say number of seconds */
3918 ast_say_number(mychannel
, myrpt
->p
.remotetimeout
-
3919 (t
- myrpt
->last_activity_time
),
3920 "", mychannel
->language
, (char *) NULL
);
3922 res
= ast_waitstream(mychannel
, "");
3923 ast_stopstream(mychannel
);
3924 res
= ast_streamfile(mychannel
, "queue-seconds", mychannel
->language
);
3927 case ACT_TIMEOUT_WARNING
:
3929 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3931 res
= ast_waitstream(mychannel
, "");
3933 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3934 ast_stopstream(mychannel
);
3935 ast_say_character_str(mychannel
,myrpt
->name
,NULL
,mychannel
->language
);
3936 res
= ast_streamfile(mychannel
, "rpt/act-timeout-warning", mychannel
->language
);
3938 res
= ast_waitstream(mychannel
, "");
3940 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3941 ast_stopstream(mychannel
);
3942 if(!res
) /* Say number of seconds */
3943 ast_say_number(mychannel
, myrpt
->p
.remoteinacttimeout
-
3944 (t
- myrpt
->last_activity_time
),
3945 "", mychannel
->language
, (char *) NULL
);
3947 res
= ast_waitstream(mychannel
, "");
3948 ast_stopstream(mychannel
);
3949 res
= ast_streamfile(mychannel
, "queue-seconds", mychannel
->language
);
3953 wait_interval(myrpt
, DLY_TELEM
, mychannel
); /* Wait a little bit */
3955 rpt_localtime(&t
, &localtm
);
3956 /* Say the phase of the day is before the time */
3957 if((localtm
.tm_hour
>= 0) && (localtm
.tm_hour
< 12))
3958 p
= "rpt/goodmorning";
3959 else if((localtm
.tm_hour
>= 12) && (localtm
.tm_hour
< 18))
3960 p
= "rpt/goodafternoon";
3962 p
= "rpt/goodevening";
3963 if (sayfile(mychannel
,p
) == -1)
3968 /* Say the time is ... */
3969 if (sayfile(mychannel
,"rpt/thetimeis") == -1)
3975 res
= ast_say_time(mychannel
, t
, "", mychannel
->language
);
3977 res
= ast_waitstream(mychannel
, "");
3978 ast_stopstream(mychannel
);
3982 p
= strstr(tdesc
, "version");
3985 if(sscanf(p
, "version %d.%d", &vmajor
, &vminor
) != 2)
3987 wait_interval(myrpt
, DLY_TELEM
, mychannel
); /* Wait a little bit */
3989 if (sayfile(mychannel
,"rpt/version") == -1)
3994 if(!res
) /* Say "X" */
3995 ast_say_number(mychannel
, vmajor
, "", mychannel
->language
, (char *) NULL
);
3997 res
= ast_waitstream(mychannel
, "");
3998 ast_stopstream(mychannel
);
3999 if (saycharstr(mychannel
,".") == -1)
4004 if(!res
) /* Say "Y" */
4005 ast_say_number(mychannel
, vminor
, "", mychannel
->language
, (char *) NULL
);
4007 res
= ast_waitstream(mychannel
, "");
4008 ast_stopstream(mychannel
);
4011 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
4015 wait_interval(myrpt
, DLY_TELEM
, mychannel
); /* Wait a little bit */
4017 saycharstr(mychannel
, mytele
->param
);
4021 wait_interval(myrpt
, DLY_TELEM
, mychannel
); /* Wait a little bit */
4024 /* Parts of this section taken from app_parkandannounce */
4025 char *tpl_working
, *tpl_current
;
4026 char *tmp
[100], *myparm
;
4027 int looptemp
=0,i
=0, dres
= 0;
4030 tpl_working
= strdupa(mytele
->param
);
4031 myparm
= strsep(&tpl_working
,",");
4032 tpl_current
=strsep(&tpl_working
, ":");
4034 while(tpl_current
&& looptemp
< sizeof(tmp
)) {
4035 tmp
[looptemp
]=tpl_current
;
4037 tpl_current
=strsep(&tpl_working
,":");
4040 for(i
=0; i
<looptemp
; i
++) {
4041 if(!strcmp(tmp
[i
], "PARKED")) {
4042 ast_say_digits(mychannel
, atoi(myparm
), "", mychannel
->language
);
4043 } else if(!strcmp(tmp
[i
], "NODE")) {
4044 ast_say_digits(mychannel
, atoi(myrpt
->name
), "", mychannel
->language
);
4046 dres
= ast_streamfile(mychannel
, tmp
[i
], mychannel
->language
);
4048 dres
= ast_waitstream(mychannel
, "");
4050 ast_log(LOG_WARNING
, "ast_streamfile of %s failed on %s\n", tmp
[i
], mychannel
->name
);
4060 if (myrpt
->stopgen
) break;
4061 myrpt
->stopgen
= -1;
4062 if ((res
= ast_tonepair_start(mychannel
, 1004.0, 0, 99999999, 7200.0)))
4067 while(mychannel
->generatordata
&& (myrpt
->stopgen
<= 0)) {
4068 if (ast_safe_sleep(mychannel
,1)) break;
4079 res
= ast_waitstream(mychannel
, "");
4081 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
4085 ast_stopstream(mychannel
);
4086 rpt_mutex_lock(&myrpt
->lock
);
4087 if (mytele
->mode
== TAILMSG
)
4091 myrpt
->tailmessagen
++;
4092 if(myrpt
->tailmessagen
>= myrpt
->p
.tailmessagemax
) myrpt
->tailmessagen
= 0;
4096 myrpt
->tmsgtimer
= myrpt
->p
.tailsquashedtime
;
4099 remque((struct qelem
*)mytele
);
4100 rpt_mutex_unlock(&myrpt
->lock
);
4102 ast_hangup(mychannel
);
4103 #ifdef APP_RPT_LOCK_DEBUG
4105 struct lockthread
*t
;
4108 ast_mutex_lock(&locklock
);
4109 t
= get_lockthread(pthread_self());
4110 if (t
) memset(t
,0,sizeof(struct lockthread
));
4111 ast_mutex_unlock(&locklock
);
4117 static void rpt_telemetry(struct rpt
*myrpt
,int mode
, void *data
)
4119 struct rpt_tele
*tele
;
4120 struct rpt_link
*mylink
= (struct rpt_link
*) data
;
4122 pthread_attr_t attr
;
4124 tele
= malloc(sizeof(struct rpt_tele
));
4127 ast_log(LOG_WARNING
, "Unable to allocate memory\n");
4132 memset((char *)tele
,0,sizeof(struct rpt_tele
));
4135 rpt_mutex_lock(&myrpt
->lock
);
4136 if((mode
== CONNFAIL
) || (mode
== REMDISC
) || (mode
== CONNECTED
) ||
4137 (mode
== LINKUNKEY
)){
4138 memset(&tele
->mylink
,0,sizeof(struct rpt_link
));
4140 memcpy(&tele
->mylink
,mylink
,sizeof(struct rpt_link
));
4143 else if ((mode
== ARB_ALPHA
) || (mode
== REV_PATCH
)) {
4144 strncpy(tele
->param
, (char *) data
, TELEPARAMSIZE
- 1);
4145 tele
->param
[TELEPARAMSIZE
- 1] = 0;
4147 if (mode
== REMXXX
) tele
->submode
= (int) data
;
4148 insque((struct qelem
*)tele
, (struct qelem
*)myrpt
->tele
.next
);
4149 rpt_mutex_unlock(&myrpt
->lock
);
4150 pthread_attr_init(&attr
);
4151 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
4152 res
= ast_pthread_create(&tele
->threadid
,&attr
,rpt_tele_thread
,(void *) tele
);
4154 rpt_mutex_lock(&myrpt
->lock
);
4155 remque((struct qlem
*) tele
); /* We don't like stuck transmitters, remove it from the queue */
4156 rpt_mutex_unlock(&myrpt
->lock
);
4157 ast_log(LOG_WARNING
, "Could not create telemetry thread: %s",strerror(res
));
4162 static void *rpt_call(void *this)
4164 ZT_CONFINFO ci
; /* conference info */
4165 struct rpt
*myrpt
= (struct rpt
*)this;
4167 int stopped
,congstarted
,dialtimer
,lastcidx
,aborted
;
4168 struct ast_channel
*mychannel
,*genchannel
;
4172 /* allocate a pseudo-channel thru asterisk */
4173 mychannel
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
4176 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
4179 #ifdef AST_CDR_FLAG_POST_DISABLED
4180 ast_set_flag(mychannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
4183 ci
.confno
= myrpt
->conf
; /* use the pseudo conference */
4184 ci
.confmode
= ZT_CONF_REALANDPSEUDO
| ZT_CONF_TALKER
| ZT_CONF_LISTENER
4185 | ZT_CONF_PSEUDO_TALKER
| ZT_CONF_PSEUDO_LISTENER
;
4186 /* first put the channel on the conference */
4187 if (ioctl(mychannel
->fds
[0],ZT_SETCONF
,&ci
) == -1)
4189 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
4190 ast_hangup(mychannel
);
4191 myrpt
->callmode
= 0;
4194 /* allocate a pseudo-channel thru asterisk */
4195 genchannel
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
4198 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
4199 ast_hangup(mychannel
);
4202 #ifdef AST_CDR_FLAG_POST_DISABLED
4203 ast_set_flag(genchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
4206 ci
.confno
= myrpt
->conf
;
4207 ci
.confmode
= ZT_CONF_REALANDPSEUDO
| ZT_CONF_TALKER
| ZT_CONF_LISTENER
4208 | ZT_CONF_PSEUDO_TALKER
| ZT_CONF_PSEUDO_LISTENER
;
4209 /* first put the channel on the conference */
4210 if (ioctl(genchannel
->fds
[0],ZT_SETCONF
,&ci
) == -1)
4212 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
4213 ast_hangup(mychannel
);
4214 ast_hangup(genchannel
);
4215 myrpt
->callmode
= 0;
4218 if (myrpt
->p
.tonezone
&& (tone_zone_set_zone(mychannel
->fds
[0],myrpt
->p
.tonezone
) == -1))
4220 ast_log(LOG_WARNING
, "Unable to set tone zone %s\n",myrpt
->p
.tonezone
);
4221 ast_hangup(mychannel
);
4222 ast_hangup(genchannel
);
4223 myrpt
->callmode
= 0;
4226 if (myrpt
->p
.tonezone
&& (tone_zone_set_zone(genchannel
->fds
[0],myrpt
->p
.tonezone
) == -1))
4228 ast_log(LOG_WARNING
, "Unable to set tone zone %s\n",myrpt
->p
.tonezone
);
4229 ast_hangup(mychannel
);
4230 ast_hangup(genchannel
);
4231 myrpt
->callmode
= 0;
4234 /* start dialtone if patchquiet is 0. Special patch modes don't send dial tone */
4235 if ((!myrpt
->patchquiet
) && (tone_zone_play_tone(mychannel
->fds
[0],ZT_TONE_DIALTONE
) < 0))
4237 ast_log(LOG_WARNING
, "Cannot start dialtone\n");
4238 ast_hangup(mychannel
);
4239 ast_hangup(genchannel
);
4240 myrpt
->callmode
= 0;
4250 while ((myrpt
->callmode
== 1) || (myrpt
->callmode
== 4))
4253 if((myrpt
->patchdialtime
)&&(myrpt
->callmode
== 1)&&(myrpt
->cidx
!= lastcidx
)){
4255 lastcidx
= myrpt
->cidx
;
4258 if((myrpt
->patchdialtime
)&&(dialtimer
>= myrpt
->patchdialtime
)){
4259 rpt_mutex_lock(&myrpt
->lock
);
4261 myrpt
->callmode
= 0;
4262 rpt_mutex_unlock(&myrpt
->lock
);
4266 if ((!myrpt
->patchquiet
) && (!stopped
) && (myrpt
->callmode
== 1) && (myrpt
->cidx
> 0))
4269 /* stop dial tone */
4270 tone_zone_play_tone(mychannel
->fds
[0],-1);
4272 if (myrpt
->callmode
== 4)
4276 /* start congestion tone */
4277 tone_zone_play_tone(mychannel
->fds
[0],ZT_TONE_CONGESTION
);
4280 res
= ast_safe_sleep(mychannel
, MSWAIT
);
4283 ast_hangup(mychannel
);
4284 ast_hangup(genchannel
);
4285 rpt_mutex_lock(&myrpt
->lock
);
4286 myrpt
->callmode
= 0;
4287 rpt_mutex_unlock(&myrpt
->lock
);
4290 dialtimer
+= MSWAIT
;
4292 /* stop any tone generation */
4293 tone_zone_play_tone(mychannel
->fds
[0],-1);
4295 if (!myrpt
->callmode
)
4297 ast_hangup(mychannel
);
4298 ast_hangup(genchannel
);
4299 rpt_mutex_lock(&myrpt
->lock
);
4300 myrpt
->callmode
= 0;
4301 rpt_mutex_unlock(&myrpt
->lock
);
4302 if((!myrpt
->patchquiet
) && aborted
)
4303 rpt_telemetry(myrpt
, TERM
, NULL
);
4307 if (myrpt
->p
.ourcallerid
&& *myrpt
->p
.ourcallerid
){
4308 char *name
, *loc
, *instr
;
4309 instr
= strdup(myrpt
->p
.ourcallerid
);
4311 ast_callerid_parse(instr
, &name
, &loc
);
4313 if(mychannel
->cid
.cid_num
)
4314 free(mychannel
->cid
.cid_num
);
4315 mychannel
->cid
.cid_num
= strdup(loc
);
4318 if(mychannel
->cid
.cid_name
)
4319 free(mychannel
->cid
.cid_name
);
4320 mychannel
->cid
.cid_name
= strdup(name
);
4326 ast_copy_string(mychannel
->exten
, myrpt
->exten
, sizeof(mychannel
->exten
) - 1);
4327 ast_copy_string(mychannel
->context
, myrpt
->patchcontext
, sizeof(mychannel
->context
) - 1);
4329 if (myrpt
->p
.acctcode
)
4330 ast_cdr_setaccount(mychannel
,myrpt
->p
.acctcode
);
4331 mychannel
->priority
= 1;
4332 ast_channel_undefer_dtmf(mychannel
);
4333 if (ast_pbx_start(mychannel
) < 0)
4335 ast_log(LOG_WARNING
, "Unable to start PBX!!\n");
4336 ast_hangup(mychannel
);
4337 ast_hangup(genchannel
);
4338 rpt_mutex_lock(&myrpt
->lock
);
4339 myrpt
->callmode
= 0;
4340 rpt_mutex_unlock(&myrpt
->lock
);
4344 rpt_mutex_lock(&myrpt
->lock
);
4345 myrpt
->callmode
= 3;
4346 /* set appropriate conference for the pseudo */
4348 ci
.confno
= myrpt
->conf
;
4349 ci
.confmode
= (myrpt
->p
.duplex
== 2) ? ZT_CONF_CONFANNMON
:
4350 (ZT_CONF_CONF
| ZT_CONF_LISTENER
| ZT_CONF_TALKER
);
4351 /* first put the channel on the conference in announce mode */
4352 if (ioctl(myrpt
->pchannel
->fds
[0],ZT_SETCONF
,&ci
) == -1)
4354 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
4355 ast_hangup(mychannel
);
4356 ast_hangup(genchannel
);
4357 myrpt
->callmode
= 0;
4360 while(myrpt
->callmode
)
4362 if ((!mychannel
->pbx
) && (myrpt
->callmode
!= 4))
4364 if(myrpt
->patchfarenddisconnect
){ /* If patch is setup for far end disconnect */
4365 myrpt
->callmode
= 0;
4366 if(!myrpt
->patchquiet
){
4367 rpt_mutex_unlock(&myrpt
->lock
);
4368 rpt_telemetry(myrpt
, TERM
, NULL
);
4369 rpt_mutex_lock(&myrpt
->lock
);
4372 else{ /* Send congestion until patch is downed by command */
4373 myrpt
->callmode
= 4;
4374 rpt_mutex_unlock(&myrpt
->lock
);
4375 /* start congestion tone */
4376 tone_zone_play_tone(genchannel
->fds
[0],ZT_TONE_CONGESTION
);
4377 rpt_mutex_lock(&myrpt
->lock
);
4382 struct ast_frame wf
= {AST_FRAME_DTMF
, } ;
4383 wf
.subclass
= myrpt
->mydtmf
;
4384 rpt_mutex_unlock(&myrpt
->lock
);
4385 ast_queue_frame(mychannel
,&wf
);
4386 ast_senddigit(genchannel
,myrpt
->mydtmf
);
4387 rpt_mutex_lock(&myrpt
->lock
);
4390 rpt_mutex_unlock(&myrpt
->lock
);
4391 usleep(MSWAIT
* 1000);
4392 rpt_mutex_lock(&myrpt
->lock
);
4394 rpt_mutex_unlock(&myrpt
->lock
);
4395 tone_zone_play_tone(genchannel
->fds
[0],-1);
4396 if (mychannel
->pbx
) ast_softhangup(mychannel
,AST_SOFTHANGUP_DEV
);
4397 ast_hangup(genchannel
);
4398 rpt_mutex_lock(&myrpt
->lock
);
4399 myrpt
->callmode
= 0;
4400 rpt_mutex_unlock(&myrpt
->lock
);
4401 /* set appropriate conference for the pseudo */
4403 ci
.confno
= myrpt
->conf
;
4404 ci
.confmode
= ((myrpt
->p
.duplex
== 2) || (myrpt
->p
.duplex
== 4)) ? ZT_CONF_CONFANNMON
:
4405 (ZT_CONF_CONF
| ZT_CONF_LISTENER
| ZT_CONF_TALKER
);
4406 /* first put the channel on the conference in announce mode */
4407 if (ioctl(myrpt
->pchannel
->fds
[0],ZT_SETCONF
,&ci
) == -1)
4409 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
4414 static void send_link_dtmf(struct rpt
*myrpt
,char c
)
4417 struct ast_frame wf
;
4420 snprintf(str
, sizeof(str
), "D %s %s %d %c", myrpt
->cmdnode
, myrpt
->name
, ++(myrpt
->dtmfidx
), c
);
4421 wf
.frametype
= AST_FRAME_TEXT
;
4425 wf
.datalen
= strlen(str
) + 1;
4427 l
= myrpt
->links
.next
;
4428 /* first, see if our dude is there */
4429 while(l
!= &myrpt
->links
)
4431 if (l
->name
[0] == '0')
4436 /* if we found it, write it and were done */
4437 if (!strcmp(l
->name
,myrpt
->cmdnode
))
4440 if (l
->chan
) ast_write(l
->chan
,&wf
);
4445 l
= myrpt
->links
.next
;
4446 /* if not, give it to everyone */
4447 while(l
!= &myrpt
->links
)
4450 if (l
->chan
) ast_write(l
->chan
,&wf
);
4463 * 2: Already connected to this node
4466 static int connect_link(struct rpt
*myrpt
, char* node
, int mode
, int perma
)
4468 char *val
, *s
, *s1
, *s2
, *tele
;
4469 char lstr
[MAXLINKLIST
],*strs
[MAXLINKLIST
];
4470 char tmp
[300], deststr
[300] = "",modechange
= 0;
4474 ZT_CONFINFO ci
; /* conference info */
4476 val
= node_lookup(myrpt
,node
);
4478 if(strlen(node
) >= myrpt
->longestnode
)
4479 return -1; /* No such node */
4480 return 1; /* No match yet */
4483 ast_log(LOG_NOTICE
,"Connect attempt to node %s\n", node
);
4484 ast_log(LOG_NOTICE
,"Mode: %s\n",(mode
)?"Transceive":"Monitor");
4485 ast_log(LOG_NOTICE
,"Connection type: %s\n",(perma
)?"Permalink":"Normal");
4488 strncpy(tmp
,val
,sizeof(tmp
) - 1);
4490 s1
= strsep(&s
,",");
4491 s2
= strsep(&s
,",");
4492 rpt_mutex_lock(&myrpt
->lock
);
4493 l
= myrpt
->links
.next
;
4494 /* try to find this one in queue */
4495 while(l
!= &myrpt
->links
){
4496 if (l
->name
[0] == '0')
4501 /* if found matching string */
4502 if (!strcmp(l
->name
, node
))
4507 if (l
!= &myrpt
->links
){
4508 /* if already in this mode, just ignore */
4509 if ((l
->mode
) || (!l
->chan
)) {
4510 rpt_mutex_unlock(&myrpt
->lock
);
4511 return 2; /* Already linked */
4513 reconnects
= l
->reconnects
;
4514 rpt_mutex_unlock(&myrpt
->lock
);
4515 if (l
->chan
) ast_softhangup(l
->chan
, AST_SOFTHANGUP_DEV
);
4516 l
->retries
= l
->max_retries
+ 1;
4521 __mklinklist(myrpt
,NULL
,lstr
);
4522 rpt_mutex_unlock(&myrpt
->lock
);
4523 n
= finddelim(lstr
,strs
,MAXLINKLIST
);
4524 for(i
= 0; i
< n
; i
++)
4526 if ((*strs
[i
] < '0') ||
4527 (*strs
[i
] > '9')) strs
[i
]++;
4528 if (!strcmp(strs
[i
],node
))
4530 return 2; /* Already linked */
4534 strncpy(myrpt
->lastlinknode
,node
,MAXNODESTR
- 1);
4535 /* establish call */
4536 l
= malloc(sizeof(struct rpt_link
));
4539 ast_log(LOG_WARNING
, "Unable to malloc\n");
4542 /* zero the silly thing */
4543 memset((char *)l
,0,sizeof(struct rpt_link
));
4546 l
->thisconnected
= 0;
4547 strncpy(l
->name
, node
, MAXNODESTR
- 1);
4548 l
->isremote
= (s
&& ast_true(s
));
4549 if (modechange
) l
->connected
= 1;
4550 l
->hasconnected
= l
->perma
= perma
;
4551 #ifdef ALLOW_LOCAL_CHANNELS
4552 if ((strncasecmp(s1
,"iax2/", 5) == 0) || (strncasecmp(s1
, "local/", 6) == 0))
4553 strncpy(deststr
, s1
, sizeof(deststr
));
4555 snprintf(deststr
, sizeof(deststr
), "IAX2/%s", s1
);
4557 snprintf(deststr
, sizeof(deststr
), "IAX2/%s", s1
);
4559 tele
= strchr(deststr
, '/');
4561 ast_log(LOG_WARNING
,"link3:Dial number (%s) must be in format tech/number\n",deststr
);
4566 l
->chan
= ast_request(deststr
, AST_FORMAT_SLINEAR
, tele
,NULL
);
4568 ast_set_read_format(l
->chan
, AST_FORMAT_SLINEAR
);
4569 ast_set_write_format(l
->chan
, AST_FORMAT_SLINEAR
);
4570 #ifdef AST_CDR_FLAG_POST_DISABLED
4571 ast_set_flag(l
->chan
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
4573 l
->chan
->whentohangup
= 0;
4574 l
->chan
->appl
= "Apprpt";
4575 l
->chan
->data
= "(Remote Rx)";
4577 ast_log(LOG_NOTICE
, "rpt (remote) initiating call to %s/%s on %s\n",
4578 deststr
, tele
, l
->chan
->name
);
4579 if(l
->chan
->cid
.cid_num
)
4580 free(l
->chan
->cid
.cid_num
);
4581 l
->chan
->cid
.cid_num
= strdup(myrpt
->name
);
4582 ast_call(l
->chan
,tele
,999);
4586 ast_log(LOG_NOTICE
, "Unable to place call to %s/%s on %s\n",
4587 deststr
,tele
,l
->chan
->name
);
4588 if (myrpt
->p
.archivedir
)
4591 sprintf(str
,"LINKFAIL,%s",l
->name
);
4592 donodelog(myrpt
,str
);
4597 /* allocate a pseudo-channel thru asterisk */
4598 l
->pchan
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
4600 ast_log(LOG_WARNING
,"rpt connect: Sorry unable to obtain pseudo channel\n");
4601 ast_hangup(l
->chan
);
4605 ast_set_read_format(l
->pchan
, AST_FORMAT_SLINEAR
);
4606 ast_set_write_format(l
->pchan
, AST_FORMAT_SLINEAR
);
4607 #ifdef AST_CDR_FLAG_POST_DISABLED
4608 ast_set_flag(l
->pchan
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
4610 /* make a conference for the tx */
4612 ci
.confno
= myrpt
->conf
;
4613 ci
.confmode
= ZT_CONF_CONF
| ZT_CONF_LISTENER
| ZT_CONF_TALKER
;
4614 /* first put the channel on the conference in proper mode */
4615 if (ioctl(l
->pchan
->fds
[0], ZT_SETCONF
, &ci
) == -1)
4617 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
4618 ast_hangup(l
->chan
);
4619 ast_hangup(l
->pchan
);
4623 rpt_mutex_lock(&myrpt
->lock
);
4624 l
->reconnects
= reconnects
;
4625 /* insert at end of queue */
4626 l
->max_retries
= MAX_RETRIES
;
4628 l
->max_retries
= MAX_RETRIES_PERM
;
4629 if (l
->isremote
) l
->retries
= l
->max_retries
+ 1;
4630 insque((struct qelem
*)l
,(struct qelem
*)myrpt
->links
.next
);
4632 rpt_mutex_unlock(&myrpt
->lock
);
4639 * Internet linking function
4642 static int function_ilink(struct rpt
*myrpt
, char *param
, char *digits
, int command_source
, struct rpt_link
*mylink
)
4645 char *val
, *s
, *s1
, *s2
;
4647 char digitbuf
[MAXNODESTR
],*strs
[MAXLINKLIST
];
4656 if (myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
|| myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].linkfundisable
)
4659 strncpy(digitbuf
,digits
,MAXNODESTR
- 1);
4662 printf("@@@@ ilink param = %s, digitbuf = %s\n", (param
)? param
: "(null)", digitbuf
);
4664 switch(myatoi(param
)){
4665 case 11: /* Perm Link off */
4666 case 1: /* Link off */
4667 if ((digitbuf
[0] == '0') && (myrpt
->lastlinknode
[0]))
4668 strcpy(digitbuf
,myrpt
->lastlinknode
);
4669 val
= node_lookup(myrpt
,digitbuf
);
4671 if(strlen(digitbuf
) >= myrpt
->longestnode
)
4675 strncpy(tmp
,val
,sizeof(tmp
) - 1);
4677 s1
= strsep(&s
,",");
4678 s2
= strsep(&s
,",");
4679 rpt_mutex_lock(&myrpt
->lock
);
4680 l
= myrpt
->links
.next
;
4681 /* try to find this one in queue */
4682 while(l
!= &myrpt
->links
){
4683 if (l
->name
[0] == '0')
4688 /* if found matching string */
4689 if (!strcmp(l
->name
, digitbuf
))
4693 if (l
!= &myrpt
->links
){ /* if found */
4694 struct ast_frame wf
;
4696 /* must use perm command on perm link */
4697 if ((myatoi(param
) < 10) &&
4698 (l
->max_retries
> MAX_RETRIES
))
4700 rpt_mutex_unlock(&myrpt
->lock
);
4703 strncpy(myrpt
->lastlinknode
,digitbuf
,MAXNODESTR
- 1);
4704 l
->retries
= l
->max_retries
+ 1;
4706 rpt_mutex_unlock(&myrpt
->lock
);
4707 wf
.frametype
= AST_FRAME_TEXT
;
4711 wf
.datalen
= strlen(discstr
) + 1;
4716 ast_write(l
->chan
,&wf
);
4717 if (ast_safe_sleep(l
->chan
,250) == -1) return DC_ERROR
;
4718 ast_softhangup(l
->chan
,AST_SOFTHANGUP_DEV
);
4720 rpt_telemetry(myrpt
, COMPLETE
, NULL
);
4723 rpt_mutex_unlock(&myrpt
->lock
);
4725 case 2: /* Link Monitor */
4726 case 3: /* Link transceive */
4727 case 12: /* Link Monitor permanent */
4728 case 13: /* Link transceive permanent */
4729 if ((digitbuf
[0] == '0') && (myrpt
->lastlinknode
[0]))
4730 strcpy(digitbuf
,myrpt
->lastlinknode
);
4731 /* Attempt connection */
4732 perma
= (atoi(param
) > 10) ? 1 : 0;
4733 mode
= (atoi(param
) & 1) ? 1 : 0;
4734 r
= connect_link(myrpt
, digitbuf
, mode
, perma
);
4737 rpt_telemetry(myrpt
, COMPLETE
, NULL
);
4744 rpt_telemetry(myrpt
, REMALREADY
, NULL
);
4748 rpt_telemetry(myrpt
, CONNFAIL
, NULL
);
4753 case 4: /* Enter Command Mode */
4755 /* if doesnt allow link cmd, or no links active, return */
4756 if (((command_source
!= SOURCE_RPT
) &&
4757 (command_source
!= SOURCE_PHONE
) &&
4758 (command_source
!= SOURCE_DPHONE
)) ||
4759 (myrpt
->links
.next
== &myrpt
->links
))
4762 /* if already in cmd mode, or selected self, fughetabahtit */
4763 if ((myrpt
->cmdnode
[0]) || (!strcmp(myrpt
->name
, digitbuf
))){
4765 rpt_telemetry(myrpt
, REMALREADY
, NULL
);
4768 if ((digitbuf
[0] == '0') && (myrpt
->lastlinknode
[0]))
4769 strcpy(digitbuf
,myrpt
->lastlinknode
);
4770 /* node must at least exist in list */
4771 val
= node_lookup(myrpt
,digitbuf
);
4773 if(strlen(digitbuf
) >= myrpt
->longestnode
)
4778 rpt_mutex_lock(&myrpt
->lock
);
4779 strcpy(myrpt
->lastlinknode
,digitbuf
);
4780 strncpy(myrpt
->cmdnode
, digitbuf
, sizeof(myrpt
->cmdnode
) - 1);
4781 rpt_mutex_unlock(&myrpt
->lock
);
4782 rpt_telemetry(myrpt
, REMGO
, NULL
);
4785 case 5: /* Status */
4786 rpt_telemetry(myrpt
, STATUS
, NULL
);
4789 case 15: /* Full Status */
4790 rpt_telemetry(myrpt
, FULLSTATUS
, NULL
);
4794 case 6: /* All Links Off, including permalinks */
4795 rpt_mutex_lock(&myrpt
->lock
);
4796 myrpt
->savednodes
[0] = 0;
4797 l
= myrpt
->links
.next
;
4798 /* loop through all links */
4799 while(l
!= &myrpt
->links
){
4800 struct ast_frame wf
;
4801 if (l
->name
[0] == '0') /* Skip any IAXRPT monitoring */
4806 /* Make a string of disconnected nodes for possible restoration */
4807 sprintf(tmp
,"%c%c%s",(l
->mode
) ? 'X' : 'M',(l
->perma
) ? 'P':'T',l
->name
);
4808 if(strlen(tmp
) + strlen(myrpt
->savednodes
) + 1 < MAXNODESTR
){
4809 if(myrpt
->savednodes
[0])
4810 strcat(myrpt
->savednodes
, ",");
4811 strcat(myrpt
->savednodes
, tmp
);
4813 l
->retries
= l
->max_retries
+ 1;
4814 l
->disced
= 2; /* Silently disconnect */
4815 rpt_mutex_unlock(&myrpt
->lock
);
4816 /* ast_log(LOG_NOTICE,"dumping link %s\n",l->name); */
4818 wf
.frametype
= AST_FRAME_TEXT
;
4822 wf
.datalen
= strlen(discstr
) + 1;
4827 ast_write(l
->chan
,&wf
);
4828 ast_safe_sleep(l
->chan
,250); /* It's dead already, why check the return value? */
4829 ast_softhangup(l
->chan
,AST_SOFTHANGUP_DEV
);
4831 rpt_mutex_lock(&myrpt
->lock
);
4834 rpt_mutex_unlock(&myrpt
->lock
);
4836 ast_log(LOG_NOTICE
,"Nodes disconnected: %s\n",myrpt
->savednodes
);
4837 rpt_telemetry(myrpt
, COMPLETE
, NULL
);
4840 case 7: /* Identify last node which keyed us up */
4841 rpt_telemetry(myrpt
, LASTNODEKEY
, NULL
);
4845 #ifdef _MDC_DECODE_H_
4847 myrpt
->lastunit
= 0xd00d;
4848 mdc1200_notify(myrpt
,NULL
,myrpt
->lastunit
);
4849 mdc1200_send(myrpt
,myrpt
->lastunit
);
4853 case 16: /* Restore links disconnected with "disconnect all links" command */
4854 strcpy(tmp
, myrpt
->savednodes
); /* Make a copy */
4855 finddelim(tmp
, strs
, MAXLINKLIST
); /* convert into substrings */
4856 for(i
= 0; tmp
[0] && strs
[i
] != NULL
&& i
< MAXLINKLIST
; i
++){
4858 mode
= (s1
[0] == 'X') ? 1 : 0;
4859 perma
= (s1
[1] == 'P') ? 1 : 0;
4860 connect_link(myrpt
, s1
+ 2, mode
, perma
); /* Try to reconnect */
4862 rpt_telemetry(myrpt
, COMPLETE
, NULL
);
4881 if (((myrpt
->p
.propagate_dtmf
) &&
4882 (command_source
== SOURCE_LNK
)) ||
4883 ((myrpt
->p
.propagate_phonedtmf
) &&
4884 ((command_source
== SOURCE_PHONE
) ||
4885 (command_source
== SOURCE_DPHONE
))))
4886 do_dtmf_local(myrpt
,
4887 remdtmfstr
[myatoi(param
) - 200]);
4893 return DC_INDETERMINATE
;
4900 static int function_autopatchup(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
4902 pthread_attr_t attr
;
4903 int i
, index
, paramlength
;
4906 char *paramlist
[20];
4908 static char *keywords
[] = {
4917 if (myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
|| myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].autopatchdisable
)
4921 printf("@@@@ Autopatch up\n");
4923 if(!myrpt
->callmode
){
4925 myrpt
->patchnoct
= 0;
4926 myrpt
->patchdialtime
= 0;
4927 myrpt
->patchfarenddisconnect
= 0;
4928 myrpt
->patchquiet
= 0;
4929 strncpy(myrpt
->patchcontext
, myrpt
->p
.ourcontext
, MAXPATCHCONTEXT
);
4932 /* Process parameter list */
4933 lparam
= ast_strdupa(param
);
4935 ast_log(LOG_ERROR
,"App_rpt out of memory on line %d\n",__LINE__
);
4938 paramlength
= finddelim(lparam
, paramlist
, 20);
4939 for(i
= 0; i
< paramlength
; i
++){
4940 index
= matchkeyword(paramlist
[i
], &value
, keywords
);
4942 value
= skipchars(value
, "= ");
4945 case 1: /* context */
4946 strncpy(myrpt
->patchcontext
, value
, MAXPATCHCONTEXT
- 1) ;
4949 case 2: /* dialtime */
4950 myrpt
->patchdialtime
= atoi(value
);
4953 case 3: /* farenddisconnect */
4954 myrpt
->patchfarenddisconnect
= atoi(value
);
4958 myrpt
->patchnoct
= atoi(value
);
4962 myrpt
->patchquiet
= atoi(value
);
4972 rpt_mutex_lock(&myrpt
->lock
);
4974 /* if on call, force * into current audio stream */
4976 if ((myrpt
->callmode
== 2) || (myrpt
->callmode
== 3)){
4977 myrpt
->mydtmf
= myrpt
->p
.endchar
;
4979 if (myrpt
->callmode
){
4980 rpt_mutex_unlock(&myrpt
->lock
);
4983 myrpt
->callmode
= 1;
4985 myrpt
->exten
[myrpt
->cidx
] = 0;
4986 rpt_mutex_unlock(&myrpt
->lock
);
4987 pthread_attr_init(&attr
);
4988 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
4989 ast_pthread_create(&myrpt
->rpt_call_thread
,&attr
,rpt_call
,(void *) myrpt
);
4997 static int function_autopatchdn(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
4999 if (myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
|| myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].autopatchdisable
)
5003 printf("@@@@ Autopatch down\n");
5005 rpt_mutex_lock(&myrpt
->lock
);
5007 if (!myrpt
->callmode
){
5008 rpt_mutex_unlock(&myrpt
->lock
);
5012 myrpt
->callmode
= 0;
5013 rpt_mutex_unlock(&myrpt
->lock
);
5014 rpt_telemetry(myrpt
, TERM
, NULL
);
5022 static int function_status(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
5028 if ((myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
) || (myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].userfundisable
))
5032 printf("@@@@ status param = %s, digitbuf = %s\n", (param
)? param
: "(null)", digitbuf
);
5034 switch(myatoi(param
)){
5035 case 1: /* System ID */
5036 rpt_telemetry(myrpt
, ID1
, NULL
);
5038 case 2: /* System Time */
5039 rpt_telemetry(myrpt
, STATS_TIME
, NULL
);
5041 case 3: /* app_rpt.c version */
5042 rpt_telemetry(myrpt
, STATS_VERSION
, NULL
);
5046 return DC_INDETERMINATE
;
5050 * Macro-oni (without Salami)
5053 static int function_macro(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
5062 printf("@@@@ macro-oni param = %s, digitbuf = %s\n", (param
)? param
: "(null)", digitbuf
);
5064 if(strlen(digitbuf
) < 1) /* needs 1 digit */
5065 return DC_INDETERMINATE
;
5067 for(i
= 0 ; i
< digitbuf
[i
] ; i
++) {
5068 if((digitbuf
[i
] < '0') || (digitbuf
[i
] > '9'))
5072 if (*digitbuf
== '0') val
= myrpt
->p
.startupmacro
;
5073 else val
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->p
.macro
, digitbuf
);
5074 /* param was 1 for local buf */
5076 if (strlen(digitbuf
) < myrpt
->macro_longest
)
5077 return DC_INDETERMINATE
;
5078 rpt_telemetry(myrpt
, MACRO_NOTFOUND
, NULL
);
5081 rpt_mutex_lock(&myrpt
->lock
);
5082 if ((MAXMACRO
- strlen(myrpt
->macrobuf
)) < strlen(val
))
5084 rpt_mutex_unlock(&myrpt
->lock
);
5085 rpt_telemetry(myrpt
, MACRO_BUSY
, NULL
);
5088 myrpt
->macrotimer
= MACROTIME
;
5089 strncat(myrpt
->macrobuf
, val
, MAXMACRO
- strlen(myrpt
->macrobuf
) - 1);
5090 rpt_mutex_unlock(&myrpt
->lock
);
5095 * COP - Control operator
5098 static int function_cop(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
5105 switch(myatoi(param
)){
5106 case 1: /* System reset */
5107 system("killall -9 asterisk");
5111 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
= 0;
5112 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "RPTENA");
5116 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
= 1;
5119 case 4: /* test tone on */
5120 if (myrpt
->stopgen
< 0)
5127 rpt_telemetry(myrpt
, TEST_TONE
, NULL
);
5131 case 5: /* Disgorge variables to log for debug purposes */
5132 myrpt
->disgorgetime
= time(NULL
) + 10; /* Do it 10 seconds later */
5135 case 6: /* Simulate COR being activated (phone only) */
5136 if (command_source
!= SOURCE_PHONE
) return DC_INDETERMINATE
;
5140 case 7: /* Time out timer enable */
5141 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].totdisable
= 0;
5142 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "TOTENA");
5145 case 8: /* Time out timer disable */
5146 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].totdisable
= 1;
5147 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "TOTDIS");
5150 case 9: /* Autopatch enable */
5151 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].autopatchdisable
= 0;
5152 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "APENA");
5155 case 10: /* Autopatch disable */
5156 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].autopatchdisable
= 1;
5157 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "APDIS");
5160 case 11: /* Link Enable */
5161 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].linkfundisable
= 0;
5162 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "LNKENA");
5165 case 12: /* Link Disable */
5166 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].linkfundisable
= 1;
5167 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "LNKDIS");
5170 case 13: /* Query System State */
5171 string
[0] = string
[1] = 'S';
5172 string
[2] = myrpt
->p
.sysstate_cur
+ '0';
5174 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) string
);
5177 case 14: /* Change System State */
5178 if(strlen(digitbuf
) == 0)
5180 if((digitbuf
[0] < '0') || (digitbuf
[0] > '9'))
5182 myrpt
->p
.sysstate_cur
= digitbuf
[0] - '0';
5183 string
[0] = string
[1] = 'S';
5184 string
[2] = myrpt
->p
.sysstate_cur
+ '0';
5186 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) string
);
5189 case 15: /* Scheduler Enable */
5190 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].schedulerdisable
= 0;
5191 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "SKENA");
5194 case 16: /* Scheduler Disable */
5195 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].schedulerdisable
= 1;
5196 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "SKDIS");
5199 case 17: /* User functions Enable */
5200 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].userfundisable
= 0;
5201 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "UFENA");
5204 case 18: /* User Functions Disable */
5205 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].userfundisable
= 1;
5206 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "UFDIS");
5209 case 19: /* Alternate Tail Enable */
5210 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].alternatetail
= 1;
5211 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "ATENA");
5214 case 20: /* Alternate Tail Disable */
5215 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].alternatetail
= 0;
5216 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "ATDIS");
5219 return DC_INDETERMINATE
;
5223 * Collect digits one by one until something matches
5226 static int collect_function_digits(struct rpt
*myrpt
, char *digits
,
5227 int command_source
, struct rpt_link
*mylink
)
5230 char *stringp
,*action
,*param
,*functiondigits
;
5231 char function_table_name
[30] = "";
5232 char workstring
[200];
5234 struct ast_variable
*vp
;
5237 printf("@@@@ Digits collected: %s, source: %d\n", digits
, command_source
);
5239 if (command_source
== SOURCE_DPHONE
) {
5240 if (!myrpt
->p
.dphone_functions
) return DC_INDETERMINATE
;
5241 strncpy(function_table_name
, myrpt
->p
.dphone_functions
, sizeof(function_table_name
) - 1);
5243 else if (command_source
== SOURCE_PHONE
) {
5244 if (!myrpt
->p
.phone_functions
) return DC_INDETERMINATE
;
5245 strncpy(function_table_name
, myrpt
->p
.phone_functions
, sizeof(function_table_name
) - 1);
5247 else if (command_source
== SOURCE_LNK
)
5248 strncpy(function_table_name
, myrpt
->p
.link_functions
, sizeof(function_table_name
) - 1);
5250 strncpy(function_table_name
, myrpt
->p
.functions
, sizeof(function_table_name
) - 1);
5251 vp
= ast_variable_browse(myrpt
->cfg
, function_table_name
);
5253 if(!strncasecmp(vp
->name
, digits
, strlen(vp
->name
)))
5260 n
= myrpt
->longestfunc
;
5261 if (command_source
== SOURCE_LNK
) n
= myrpt
->link_longestfunc
;
5263 if (command_source
== SOURCE_PHONE
) n
= myrpt
->phone_longestfunc
;
5265 if (command_source
== SOURCE_DPHONE
) n
= myrpt
->dphone_longestfunc
;
5267 if(strlen(digits
) >= n
)
5270 return DC_INDETERMINATE
;
5272 /* Found a match, retrieve value part and parse */
5273 strncpy(workstring
, vp
->value
, sizeof(workstring
) - 1 );
5274 stringp
= workstring
;
5275 action
= strsep(&stringp
, ",");
5278 printf("@@@@ action: %s, param = %s\n",action
, (param
) ? param
: "(null)");
5279 /* Look up the action */
5280 for(i
= 0 ; i
< (sizeof(function_table
)/sizeof(struct function_table_tag
)); i
++){
5281 if(!strncasecmp(action
, function_table
[i
].action
, strlen(action
)))
5285 printf("@@@@ table index i = %d\n",i
);
5286 if(i
== (sizeof(function_table
)/sizeof(struct function_table_tag
))){
5287 /* Error, action not in table */
5290 if(function_table
[i
].function
== NULL
){
5291 /* Error, function undefined */
5293 printf("@@@@ NULL for action: %s\n",action
);
5296 functiondigits
= digits
+ strlen(vp
->name
);
5297 return (*function_table
[i
].function
)(myrpt
, param
, functiondigits
, command_source
, mylink
);
5301 static void handle_link_data(struct rpt
*myrpt
, struct rpt_link
*mylink
,
5304 char tmp
[512],cmd
[300] = "",dest
[300],src
[300],c
;
5307 struct ast_frame wf
;
5309 wf
.frametype
= AST_FRAME_TEXT
;
5313 wf
.datalen
= strlen(str
) + 1;
5315 /* put string in our buffer */
5316 strncpy(tmp
,str
,sizeof(tmp
) - 1);
5318 if (!strcmp(tmp
,discstr
))
5321 mylink
->retries
= mylink
->max_retries
+ 1;
5322 ast_softhangup(mylink
->chan
,AST_SOFTHANGUP_DEV
);
5327 rpt_mutex_lock(&myrpt
->lock
);
5328 strcpy(mylink
->linklist
,tmp
+ 2);
5329 time(&mylink
->linklistreceived
);
5330 rpt_mutex_unlock(&myrpt
->lock
);
5331 if (debug
> 6) ast_log(LOG_NOTICE
,"@@@@ node %s recieved node list %s from node %s\n",
5332 myrpt
->name
,tmp
,mylink
->name
);
5337 if (sscanf(tmp
,"%s %s %x",cmd
,src
,&seq
) != 3)
5339 ast_log(LOG_WARNING
, "Unable to parse ident string %s\n",str
);
5342 mdc1200_notify(myrpt
,src
,seq
);
5347 if (sscanf(tmp
,"%s %s %s %d %c",cmd
,dest
,src
,&seq
,&c
) != 5)
5349 ast_log(LOG_WARNING
, "Unable to parse link string %s\n",str
);
5352 if (strcmp(cmd
,"D"))
5354 ast_log(LOG_WARNING
, "Unable to parse link string %s\n",str
);
5360 strcpy(dest
,myrpt
->name
);
5363 /* if not for me, redistribute to all links */
5364 if (strcmp(dest
,myrpt
->name
))
5366 l
= myrpt
->links
.next
;
5367 /* see if this is one in list */
5368 while(l
!= &myrpt
->links
)
5370 if (l
->name
[0] == '0')
5375 /* dont send back from where it came */
5376 if ((l
== mylink
) || (!strcmp(l
->name
,mylink
->name
)))
5381 /* if it is, send it and we're done */
5382 if (!strcmp(l
->name
,dest
))
5384 /* send, but not to src */
5385 if (strcmp(l
->name
,src
)) {
5387 if (l
->chan
) ast_write(l
->chan
,&wf
);
5393 l
= myrpt
->links
.next
;
5394 /* otherwise, send it to all of em */
5395 while(l
!= &myrpt
->links
)
5397 if (l
->name
[0] == '0')
5402 /* dont send back from where it came */
5403 if ((l
== mylink
) || (!strcmp(l
->name
,mylink
->name
)))
5408 /* send, but not to src */
5409 if (strcmp(l
->name
,src
)) {
5411 if (l
->chan
) ast_write(l
->chan
,&wf
);
5417 if (myrpt
->p
.archivedir
)
5421 sprintf(str
,"DTMF,%s,%c",mylink
->name
,c
);
5422 donodelog(myrpt
,str
);
5424 c
= func_xlat(myrpt
,c
,&myrpt
->p
.outxlat
);
5426 rpt_mutex_lock(&myrpt
->lock
);
5427 if (c
== myrpt
->p
.endchar
) myrpt
->stopgen
= 1;
5428 if (myrpt
->callmode
== 1)
5430 myrpt
->exten
[myrpt
->cidx
++] = c
;
5431 myrpt
->exten
[myrpt
->cidx
] = 0;
5432 /* if this exists */
5433 if (ast_exists_extension(myrpt
->pchannel
,myrpt
->patchcontext
,myrpt
->exten
,1,NULL
))
5435 myrpt
->callmode
= 2;
5436 if(!myrpt
->patchquiet
){
5437 rpt_mutex_unlock(&myrpt
->lock
);
5438 rpt_telemetry(myrpt
,PROC
,NULL
);
5439 rpt_mutex_lock(&myrpt
->lock
);
5442 /* if can continue, do so */
5443 if (!ast_canmatch_extension(myrpt
->pchannel
,myrpt
->patchcontext
,myrpt
->exten
,1,NULL
))
5445 /* call has failed, inform user */
5446 myrpt
->callmode
= 4;
5449 if (c
== myrpt
->p
.funcchar
)
5451 myrpt
->rem_dtmfidx
= 0;
5452 myrpt
->rem_dtmfbuf
[myrpt
->rem_dtmfidx
] = 0;
5453 time(&myrpt
->rem_dtmf_time
);
5454 rpt_mutex_unlock(&myrpt
->lock
);
5457 else if (myrpt
->rem_dtmfidx
< 0)
5459 if ((myrpt
->callmode
== 2) || (myrpt
->callmode
== 3))
5463 if (myrpt
->p
.propagate_dtmf
) do_dtmf_local(myrpt
,c
);
5464 if (myrpt
->p
.propagate_phonedtmf
) do_dtmf_phone(myrpt
,mylink
,c
);
5465 rpt_mutex_unlock(&myrpt
->lock
);
5468 else if ((c
!= myrpt
->p
.endchar
) && (myrpt
->rem_dtmfidx
>= 0))
5470 time(&myrpt
->rem_dtmf_time
);
5471 if (myrpt
->rem_dtmfidx
< MAXDTMF
)
5473 myrpt
->rem_dtmfbuf
[myrpt
->rem_dtmfidx
++] = c
;
5474 myrpt
->rem_dtmfbuf
[myrpt
->rem_dtmfidx
] = 0;
5476 rpt_mutex_unlock(&myrpt
->lock
);
5477 strncpy(cmd
, myrpt
->rem_dtmfbuf
, sizeof(cmd
) - 1);
5478 res
= collect_function_digits(myrpt
, cmd
, SOURCE_LNK
, mylink
);
5479 rpt_mutex_lock(&myrpt
->lock
);
5483 case DC_INDETERMINATE
:
5487 myrpt
->rem_dtmfidx
= 0;
5488 myrpt
->rem_dtmfbuf
[0] = 0;
5493 case DC_COMPLETEQUIET
:
5494 myrpt
->totalexecdcommands
++;
5495 myrpt
->dailyexecdcommands
++;
5496 strncpy(myrpt
->lastdtmfcommand
, cmd
, MAXDTMF
-1);
5497 myrpt
->lastdtmfcommand
[MAXDTMF
-1] = '\0';
5498 myrpt
->rem_dtmfbuf
[0] = 0;
5499 myrpt
->rem_dtmfidx
= -1;
5500 myrpt
->rem_dtmf_time
= 0;
5505 myrpt
->rem_dtmfbuf
[0] = 0;
5506 myrpt
->rem_dtmfidx
= -1;
5507 myrpt
->rem_dtmf_time
= 0;
5513 rpt_mutex_unlock(&myrpt
->lock
);
5517 static void handle_link_phone_dtmf(struct rpt
*myrpt
, struct rpt_link
*mylink
,
5524 if (myrpt
->p
.archivedir
)
5528 sprintf(str
,"DTMF(P),%s,%c",mylink
->name
,c
);
5529 donodelog(myrpt
,str
);
5531 rpt_mutex_lock(&myrpt
->lock
);
5532 if (c
== myrpt
->p
.endchar
)
5537 rpt_mutex_unlock(&myrpt
->lock
);
5541 if (myrpt
->cmdnode
[0])
5543 myrpt
->cmdnode
[0] = 0;
5544 myrpt
->dtmfidx
= -1;
5545 myrpt
->dtmfbuf
[0] = 0;
5546 rpt_mutex_unlock(&myrpt
->lock
);
5547 rpt_telemetry(myrpt
,COMPLETE
,NULL
);
5551 if (myrpt
->cmdnode
[0])
5553 rpt_mutex_unlock(&myrpt
->lock
);
5554 send_link_dtmf(myrpt
,c
);
5557 if (myrpt
->callmode
== 1)
5559 myrpt
->exten
[myrpt
->cidx
++] = c
;
5560 myrpt
->exten
[myrpt
->cidx
] = 0;
5561 /* if this exists */
5562 if (ast_exists_extension(myrpt
->pchannel
,myrpt
->patchcontext
,myrpt
->exten
,1,NULL
))
5564 myrpt
->callmode
= 2;
5565 if(!myrpt
->patchquiet
){
5566 rpt_mutex_unlock(&myrpt
->lock
);
5567 rpt_telemetry(myrpt
,PROC
,NULL
);
5568 rpt_mutex_lock(&myrpt
->lock
);
5571 /* if can continue, do so */
5572 if (!ast_canmatch_extension(myrpt
->pchannel
,myrpt
->patchcontext
,myrpt
->exten
,1,NULL
))
5574 /* call has failed, inform user */
5575 myrpt
->callmode
= 4;
5578 if ((myrpt
->callmode
== 2) || (myrpt
->callmode
== 3))
5582 if (c
== myrpt
->p
.funcchar
)
5584 myrpt
->rem_dtmfidx
= 0;
5585 myrpt
->rem_dtmfbuf
[myrpt
->rem_dtmfidx
] = 0;
5586 time(&myrpt
->rem_dtmf_time
);
5587 rpt_mutex_unlock(&myrpt
->lock
);
5590 else if ((c
!= myrpt
->p
.endchar
) && (myrpt
->rem_dtmfidx
>= 0))
5592 time(&myrpt
->rem_dtmf_time
);
5593 if (myrpt
->rem_dtmfidx
< MAXDTMF
)
5595 myrpt
->rem_dtmfbuf
[myrpt
->rem_dtmfidx
++] = c
;
5596 myrpt
->rem_dtmfbuf
[myrpt
->rem_dtmfidx
] = 0;
5598 rpt_mutex_unlock(&myrpt
->lock
);
5599 strncpy(cmd
, myrpt
->rem_dtmfbuf
, sizeof(cmd
) - 1);
5600 switch(mylink
->phonemode
)
5603 res
= collect_function_digits(myrpt
, cmd
,
5604 SOURCE_PHONE
, mylink
);
5607 res
= collect_function_digits(myrpt
, cmd
,
5608 SOURCE_DPHONE
,mylink
);
5611 res
= collect_function_digits(myrpt
, cmd
,
5612 SOURCE_LNK
, mylink
);
5616 rpt_mutex_lock(&myrpt
->lock
);
5620 case DC_INDETERMINATE
:
5628 myrpt
->rem_dtmfidx
= 0;
5629 myrpt
->rem_dtmfbuf
[0] = 0;
5634 case DC_COMPLETEQUIET
:
5635 myrpt
->totalexecdcommands
++;
5636 myrpt
->dailyexecdcommands
++;
5637 strncpy(myrpt
->lastdtmfcommand
, cmd
, MAXDTMF
-1);
5638 myrpt
->lastdtmfcommand
[MAXDTMF
-1] = '\0';
5639 myrpt
->rem_dtmfbuf
[0] = 0;
5640 myrpt
->rem_dtmfidx
= -1;
5641 myrpt
->rem_dtmf_time
= 0;
5646 myrpt
->rem_dtmfbuf
[0] = 0;
5647 myrpt
->rem_dtmfidx
= -1;
5648 myrpt
->rem_dtmf_time
= 0;
5654 rpt_mutex_unlock(&myrpt
->lock
);
5658 /* Doug Hall RBI-1 serial data definitions:
5660 * Byte 0: Expansion external outputs
5662 * Bits 0-3 are BAND as follows:
5663 * Bits 4-5 are POWER bits as follows:
5667 * Bits 6-7 are always set
5669 * Bits 0-3 MHZ in BCD format
5670 * Bits 4-5 are offset as follows:
5674 * 03 - minus minus (whatever that is)
5675 * Bit 6 is the 0/5 KHZ bit
5676 * Bit 7 is always set
5678 * Bits 0-3 are 10 KHZ in BCD format
5679 * Bits 4-7 are 100 KHZ in BCD format
5680 * Byte 4: PL Tone code and encode/decode enable bits
5681 * Bits 0-5 are PL tone code (comspec binary codes)
5682 * Bit 6 is encode enable/disable
5683 * Bit 7 is decode enable/disable
5686 /* take the frequency from the 10 mhz digits (and up) and convert it
5689 static int rbi_mhztoband(char *str
)
5693 i
= atoi(str
) / 10; /* get the 10's of mhz */
5724 /* take a PL frequency and turn it into a code */
5725 static int rbi_pltocode(char *str
)
5730 s
= strchr(str
,'.');
5732 if (s
) i
= atoi(s
+ 1);
5733 i
+= atoi(str
) * 10;
5817 * Shift out a formatted serial bit stream
5820 static void rbi_out_parallel(struct rpt
*myrpt
,unsigned char *data
)
5825 static volatile long long delayvar
;
5827 for(i
= 0 ; i
< 5 ; i
++){
5829 for(j
= 0 ; j
< 8 ; j
++){
5831 outb(d
,myrpt
->p
.iobase
);
5833 for(delayvar
= 1; delayvar
< 15000; delayvar
++);
5835 outb(d
| 2,myrpt
->p
.iobase
);
5837 for(delayvar
= 1; delayvar
< 30000; delayvar
++);
5838 outb(d
,myrpt
->p
.iobase
);
5840 for(delayvar
= 1; delayvar
< 10000; delayvar
++);
5844 for(delayvar
= 1; delayvar
< 50000; delayvar
++);
5848 static void rbi_out(struct rpt
*myrpt
,unsigned char *data
)
5850 struct zt_radio_param r
;
5852 memset(&r
,0,sizeof(struct zt_radio_param
));
5853 r
.radpar
= ZT_RADPAR_REMMODE
;
5854 r
.data
= ZT_RADPAR_REM_RBI1
;
5855 /* if setparam ioctl fails, its probably not a pciradio card */
5856 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&r
) == -1)
5858 rbi_out_parallel(myrpt
,data
);
5861 r
.radpar
= ZT_RADPAR_REMCOMMAND
;
5862 memcpy(&r
.data
,data
,5);
5863 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&r
) == -1)
5865 ast_log(LOG_WARNING
,"Cannot send RBI command for channel %s\n",myrpt
->zaprxchannel
->name
);
5870 static int serial_remote_io(struct rpt
*myrpt
, unsigned char *txbuf
, int txbytes
,
5871 unsigned char *rxbuf
, int rxmaxbytes
, int asciiflag
)
5873 int i
,j
,index
,oldmode
,olddata
;
5874 struct zt_radio_param prm
;
5878 printf("String output was: ");
5879 for(i
= 0; i
< txbytes
; i
++)
5880 printf("%02X ", (unsigned char ) txbuf
[i
]);
5883 if (myrpt
->iofd
> 0) /* if to do out a serial port */
5885 if (rxmaxbytes
&& rxbuf
) tcflush(myrpt
->iofd
,TCIFLUSH
);
5886 if (write(myrpt
->iofd
,txbuf
,txbytes
) != txbytes
) return -1;
5887 if ((!rxmaxbytes
) || (rxbuf
== NULL
)) return(0);
5888 memset(rxbuf
,0,rxmaxbytes
);
5889 for(i
= 0; i
< rxmaxbytes
; i
++)
5891 j
= read(myrpt
->iofd
,&c
,1);
5892 if (j
< 1) return(i
);
5897 if (c
== '\r') break;
5901 printf("String returned was: ");
5902 for(j
= 0; j
< i
; j
++)
5903 printf("%02X ", (unsigned char ) rxbuf
[j
]);
5909 /* if not a zap channel, cant use pciradio stuff */
5910 if (myrpt
->rxchannel
!= myrpt
->zaprxchannel
) return -1;
5912 prm
.radpar
= ZT_RADPAR_UIOMODE
;
5913 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_RADIO_GETPARAM
,&prm
) == -1) return -1;
5915 prm
.radpar
= ZT_RADPAR_UIODATA
;
5916 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_RADIO_GETPARAM
,&prm
) == -1) return -1;
5918 prm
.radpar
= ZT_RADPAR_REMMODE
;
5919 if (asciiflag
& 1) prm
.data
= ZT_RADPAR_REM_SERIAL_ASCII
;
5920 else prm
.data
= ZT_RADPAR_REM_SERIAL
;
5921 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&prm
) == -1) return -1;
5925 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_HOOK
,&i
) == -1) return -1;
5928 prm
.radpar
= ZT_RADPAR_REMCOMMAND
;
5929 prm
.data
= rxmaxbytes
;
5930 memcpy(prm
.buf
,txbuf
,txbytes
);
5931 prm
.index
= txbytes
;
5932 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&prm
) == -1) return -1;
5936 memcpy(rxbuf
,prm
.buf
,prm
.index
);
5939 prm
.radpar
= ZT_RADPAR_REMMODE
;
5940 prm
.data
= ZT_RADPAR_REM_NONE
;
5941 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&prm
) == -1) return -1;
5945 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_HOOK
,&i
) == -1) return -1;
5947 prm
.radpar
= ZT_RADPAR_UIOMODE
;
5949 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&prm
) == -1) return -1;
5950 prm
.radpar
= ZT_RADPAR_UIODATA
;
5952 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&prm
) == -1) return -1;
5956 static int civ_cmd(struct rpt
*myrpt
,unsigned char *cmd
, int cmdlen
)
5958 unsigned char rxbuf
[100];
5961 rv
= serial_remote_io(myrpt
,cmd
,cmdlen
,rxbuf
,cmdlen
+ 6,0);
5962 if (rv
== -1) return(-1);
5963 if (rv
!= (cmdlen
+ 6)) return(1);
5964 for(i
= 0; i
< 6; i
++)
5965 if (rxbuf
[i
] != cmd
[i
]) return(1);
5966 if (rxbuf
[cmdlen
] != 0xfe) return(1);
5967 if (rxbuf
[cmdlen
+ 1] != 0xfe) return(1);
5968 if (rxbuf
[cmdlen
+ 4] != 0xfb) return(1);
5969 if (rxbuf
[cmdlen
+ 5] != 0xfd) return(1);
5973 static int sendkenwood(struct rpt
*myrpt
,char *txstr
, char *rxstr
)
5977 if (debug
) printf("Send to kenwood: %s\n",txstr
);
5978 i
= serial_remote_io(myrpt
, (unsigned char *)txstr
, strlen(txstr
),
5979 (unsigned char *)rxstr
,RAD_SERIAL_BUFLEN
- 1,3);
5980 if (i
< 0) return -1;
5981 if ((i
> 0) && (rxstr
[i
- 1] == '\r'))
5983 if (debug
) printf("Got from kenwood: %s\n",rxstr
);
5987 /* take a PL frequency and turn it into a code */
5988 static int kenwood_pltocode(char *str
)
5993 s
= strchr(str
,'.');
5995 if (s
) i
= atoi(s
+ 1);
5996 i
+= atoi(str
) * 10;
6079 static int sendrxkenwood(struct rpt
*myrpt
, char *txstr
, char *rxstr
,
6084 for(i
= 0;i
< KENWOOD_RETRIES
;i
++)
6086 j
= sendkenwood(myrpt
,txstr
,rxstr
);
6087 if (j
< 0) return(j
);
6088 if (j
== 0) continue;
6089 if (!strncmp(rxstr
,cmpstr
,strlen(cmpstr
))) return(0);
6094 static int setkenwood(struct rpt
*myrpt
)
6096 char rxstr
[RAD_SERIAL_BUFLEN
],txstr
[RAD_SERIAL_BUFLEN
],freq
[20];
6097 char mhz
[MAXREMSTR
],offset
[20],band
,decimals
[MAXREMSTR
],band1
,band2
;
6099 int offsets
[] = {0,2,1};
6100 int powers
[] = {2,1,0};
6102 if (sendrxkenwood(myrpt
,"VMC 0,0\r",rxstr
,"VMC") < 0) return -1;
6103 split_freq(mhz
, decimals
, myrpt
->freq
);
6104 if (atoi(mhz
) > 400)
6109 strcpy(offset
,"005000000");
6116 strcpy(offset
,"000600000");
6118 strcpy(freq
,"000000");
6119 strncpy(freq
,decimals
,strlen(decimals
));
6120 sprintf(txstr
,"VW %c,%05d%s,0,%d,0,%d,%d,,%02d,,%02d,%s\r",
6121 band
,atoi(mhz
),freq
,offsets
[(int)myrpt
->offset
],
6122 (myrpt
->txplon
!= 0),(myrpt
->rxplon
!= 0),
6123 kenwood_pltocode(myrpt
->txpl
),kenwood_pltocode(myrpt
->rxpl
),
6125 if (sendrxkenwood(myrpt
,txstr
,rxstr
,"VW") < 0) return -1;
6126 sprintf(txstr
,"RBN %c\r",band2
);
6127 if (sendrxkenwood(myrpt
,txstr
,rxstr
,"RBN") < 0) return -1;
6128 sprintf(txstr
,"PC %c,%d\r",band1
,powers
[(int)myrpt
->powerlevel
]);
6129 if (sendrxkenwood(myrpt
,txstr
,rxstr
,"PC") < 0) return -1;
6133 static int setrbi(struct rpt
*myrpt
)
6135 char tmp
[MAXREMSTR
] = "",*s
;
6136 unsigned char rbicmd
[5];
6137 int band
,txoffset
= 0,txpower
= 0,rxpl
;
6139 /* must be a remote system */
6140 if (!myrpt
->remote
) return(0);
6141 /* must have rbi hardware */
6142 if (strncmp(myrpt
->remote
,remote_rig_rbi
,3)) return(0);
6143 if (setrbi_check(myrpt
) == -1) return(-1);
6144 strncpy(tmp
, myrpt
->freq
, sizeof(tmp
) - 1);
6145 s
= strchr(tmp
,'.');
6146 /* if no decimal, is invalid */
6150 printf("@@@@ Frequency needs a decimal\n");
6155 if (strlen(tmp
) < 2){
6157 printf("@@@@ Bad MHz digits: %s\n", tmp
);
6163 printf("@@@@ Bad KHz digits: %s\n", s
);
6167 if ((s
[2] != '0') && (s
[2] != '5')){
6169 printf("@@@@ KHz must end in 0 or 5: %c\n", s
[2]);
6173 band
= rbi_mhztoband(tmp
);
6176 printf("@@@@ Bad Band: %s\n", tmp
);
6180 rxpl
= rbi_pltocode(myrpt
->rxpl
);
6184 printf("@@@@ Bad TX PL: %s\n", myrpt
->rxpl
);
6189 switch(myrpt
->offset
)
6201 switch(myrpt
->powerlevel
)
6214 rbicmd
[1] = band
| txpower
| 0xc0;
6215 rbicmd
[2] = (*(s
- 2) - '0') | txoffset
| 0x80;
6216 if (s
[2] == '5') rbicmd
[2] |= 0x40;
6217 rbicmd
[3] = ((*s
- '0') << 4) + (s
[1] - '0');
6219 if (myrpt
->txplon
) rbicmd
[4] |= 0x40;
6220 if (myrpt
->rxplon
) rbicmd
[4] |= 0x80;
6221 rbi_out(myrpt
,rbicmd
);
6225 static int setrbi_check(struct rpt
*myrpt
)
6227 char tmp
[MAXREMSTR
] = "",*s
;
6230 /* must be a remote system */
6231 if (!myrpt
->remote
) return(0);
6232 /* must have rbi hardware */
6233 if (strncmp(myrpt
->remote
,remote_rig_rbi
,3)) return(0);
6234 strncpy(tmp
, myrpt
->freq
, sizeof(tmp
) - 1);
6235 s
= strchr(tmp
,'.');
6236 /* if no decimal, is invalid */
6240 printf("@@@@ Frequency needs a decimal\n");
6245 if (strlen(tmp
) < 2){
6247 printf("@@@@ Bad MHz digits: %s\n", tmp
);
6253 printf("@@@@ Bad KHz digits: %s\n", s
);
6257 if ((s
[2] != '0') && (s
[2] != '5')){
6259 printf("@@@@ KHz must end in 0 or 5: %c\n", s
[2]);
6263 band
= rbi_mhztoband(tmp
);
6266 printf("@@@@ Bad Band: %s\n", tmp
);
6270 txpl
= rbi_pltocode(myrpt
->txpl
);
6274 printf("@@@@ Bad TX PL: %s\n", myrpt
->txpl
);
6280 static int check_freq_kenwood(int m
, int d
, int *defmode
)
6282 int dflmd
= REM_MODE_FM
;
6284 if (m
== 144){ /* 2 meters */
6288 else if((m
>= 145) && (m
< 148)){
6291 else if((m
>= 430) && (m
< 450)){ /* 70 centimeters */
6305 /* Check for valid rbi frequency */
6306 /* Hard coded limits now, configurable later, maybe? */
6308 static int check_freq_rbi(int m
, int d
, int *defmode
)
6310 int dflmd
= REM_MODE_FM
;
6312 if(m
== 50){ /* 6 meters */
6316 else if((m
>= 51) && ( m
< 54)){
6319 else if(m
== 144){ /* 2 meters */
6323 else if((m
>= 145) && (m
< 148)){
6326 else if((m
>= 222) && (m
< 225)){ /* 1.25 meters */
6329 else if((m
>= 430) && (m
< 450)){ /* 70 centimeters */
6332 else if((m
>= 1240) && (m
< 1300)){ /* 23 centimeters */
6346 * Convert decimals of frequency to int
6349 static int decimals2int(char *fraction
)
6352 char len
= strlen(fraction
);
6353 int multiplier
= 100000;
6358 for( i
= 0 ; i
< len
; i
++, multiplier
/= 10)
6359 res
+= (fraction
[i
] - '0') * multiplier
;
6365 * Split frequency into mhz and decimals
6368 static int split_freq(char *mhz
, char *decimals
, char *freq
)
6370 char freq_copy
[MAXREMSTR
];
6373 decp
= strchr(strncpy(freq_copy
, freq
, MAXREMSTR
),'.');
6376 strncpy(mhz
, freq_copy
, MAXREMSTR
);
6377 strcpy(decimals
, "00000");
6378 strncpy(decimals
, decp
, strlen(decp
));
6388 * Split ctcss frequency into hertz and decimal
6391 static int split_ctcss_freq(char *hertz
, char *decimal
, char *freq
)
6393 char freq_copy
[MAXREMSTR
];
6396 decp
= strchr(strncpy(freq_copy
, freq
, MAXREMSTR
),'.');
6399 strncpy(hertz
, freq_copy
, MAXREMSTR
);
6400 strncpy(decimal
, decp
, strlen(decp
));
6401 decimal
[strlen(decp
)] = '\0';
6411 * FT-897 I/O handlers
6414 /* Check to see that the frequency is valid */
6415 /* Hard coded limits now, configurable later, maybe? */
6418 static int check_freq_ft897(int m
, int d
, int *defmode
)
6420 int dflmd
= REM_MODE_FM
;
6422 if(m
== 1){ /* 160 meters */
6423 dflmd
= REM_MODE_LSB
;
6427 else if(m
== 3){ /* 80 meters */
6428 dflmd
= REM_MODE_LSB
;
6432 else if(m
== 7){ /* 40 meters */
6433 dflmd
= REM_MODE_LSB
;
6437 else if(m
== 14){ /* 20 meters */
6438 dflmd
= REM_MODE_USB
;
6442 else if(m
== 18){ /* 17 meters */
6443 dflmd
= REM_MODE_USB
;
6444 if((d
< 6800) || (d
> 16800))
6447 else if(m
== 21){ /* 15 meters */
6448 dflmd
= REM_MODE_USB
;
6449 if((d
< 20000) || (d
> 45000))
6452 else if(m
== 24){ /* 12 meters */
6453 dflmd
= REM_MODE_USB
;
6454 if((d
< 89000) || (d
> 99000))
6457 else if(m
== 28){ /* 10 meters */
6458 dflmd
= REM_MODE_USB
;
6462 dflmd
= REM_MODE_FM
;
6464 dflmd
= REM_MODE_USB
;
6468 else if(m
== 50){ /* 6 meters */
6470 dflmd
= REM_MODE_FM
;
6472 dflmd
= REM_MODE_USB
;
6475 else if((m
>= 51) && ( m
< 54)){
6476 dflmd
= REM_MODE_FM
;
6478 else if(m
== 144){ /* 2 meters */
6480 dflmd
= REM_MODE_FM
;
6482 dflmd
= REM_MODE_USB
;
6484 else if((m
>= 145) && (m
< 148)){
6485 dflmd
= REM_MODE_FM
;
6487 else if((m
>= 430) && (m
< 450)){ /* 70 centimeters */
6489 dflmd
= REM_MODE_USB
;
6491 dflmd
= REM_MODE_FM
;
6504 * Set a new frequency for the FT897
6507 static int set_freq_ft897(struct rpt
*myrpt
, char *newfreq
)
6509 unsigned char cmdstr
[5];
6511 char mhz
[MAXREMSTR
];
6512 char decimals
[MAXREMSTR
];
6516 printf("New frequency: %s\n",newfreq
);
6518 if(split_freq(mhz
, decimals
, newfreq
))
6524 /* The FT-897 likes packed BCD frequencies */
6526 cmdstr
[0] = ((m
/ 100) << 4) + ((m
% 100)/10); /* 100MHz 10Mhz */
6527 cmdstr
[1] = ((m
% 10) << 4) + (d
/ 10000); /* 1MHz 100KHz */
6528 cmdstr
[2] = (((d
% 10000)/1000) << 4) + ((d
% 1000)/ 100); /* 10KHz 1KHz */
6529 cmdstr
[3] = (((d
% 100)/10) << 4) + (d
% 10); /* 100Hz 10Hz */
6530 cmdstr
[4] = 0x01; /* command */
6532 return serial_remote_io(myrpt
, cmdstr
, 5, NULL
, 0, 0);
6536 /* ft-897 simple commands */
6538 static int simple_command_ft897(struct rpt
*myrpt
, char command
)
6540 unsigned char cmdstr
[5];
6542 memset(cmdstr
, 0, 5);
6544 cmdstr
[4] = command
;
6546 return serial_remote_io(myrpt
, cmdstr
, 5, NULL
, 0, 0);
6552 static int set_offset_ft897(struct rpt
*myrpt
, char offset
)
6554 unsigned char cmdstr
[5];
6556 memset(cmdstr
, 0, 5);
6577 return serial_remote_io(myrpt
, cmdstr
, 5, NULL
, 0, 0);
6582 static int set_mode_ft897(struct rpt
*myrpt
, char newmode
)
6584 unsigned char cmdstr
[5];
6586 memset(cmdstr
, 0, 5);
6610 return serial_remote_io(myrpt
, cmdstr
, 5, NULL
, 0, 0);
6613 /* Set tone encode and decode modes */
6615 static int set_ctcss_mode_ft897(struct rpt
*myrpt
, char txplon
, char rxplon
)
6617 unsigned char cmdstr
[5];
6619 memset(cmdstr
, 0, 5);
6621 if(rxplon
&& txplon
)
6622 cmdstr
[0] = 0x2A; /* Encode and Decode */
6623 else if (!rxplon
&& txplon
)
6624 cmdstr
[0] = 0x4A; /* Encode only */
6625 else if (rxplon
&& !txplon
)
6626 cmdstr
[0] = 0x3A; /* Encode only */
6628 cmdstr
[0] = 0x8A; /* OFF */
6632 return serial_remote_io(myrpt
, cmdstr
, 5, NULL
, 0, 0);
6636 /* Set transmit and receive ctcss tone frequencies */
6638 static int set_ctcss_freq_ft897(struct rpt
*myrpt
, char *txtone
, char *rxtone
)
6640 unsigned char cmdstr
[5];
6641 char hertz
[MAXREMSTR
],decimal
[MAXREMSTR
];
6644 memset(cmdstr
, 0, 5);
6646 if(split_ctcss_freq(hertz
, decimal
, txtone
))
6652 cmdstr
[0] = ((h
/ 100) << 4) + (h
% 100)/ 10;
6653 cmdstr
[1] = ((h
% 10) << 4) + (d
% 10);
6657 if(split_ctcss_freq(hertz
, decimal
, rxtone
))
6663 cmdstr
[2] = ((h
/ 100) << 4) + (h
% 100)/ 10;
6664 cmdstr
[3] = ((h
% 10) << 4) + (d
% 10);
6668 return serial_remote_io(myrpt
, cmdstr
, 5, NULL
, 0, 0);
6673 static int set_ft897(struct rpt
*myrpt
)
6678 printf("@@@@ lock on\n");
6680 res
= simple_command_ft897(myrpt
, 0x00); /* LOCK on */
6683 printf("@@@@ ptt off\n");
6686 res
= simple_command_ft897(myrpt
, 0x88); /* PTT off */
6689 printf("Modulation mode\n");
6692 res
= set_mode_ft897(myrpt
, myrpt
->remmode
); /* Modulation mode */
6695 printf("Split off\n");
6698 simple_command_ft897(myrpt
, 0x82); /* Split off */
6701 printf("Frequency\n");
6704 res
= set_freq_ft897(myrpt
, myrpt
->freq
); /* Frequency */
6705 if((myrpt
->remmode
== REM_MODE_FM
)){
6709 res
= set_offset_ft897(myrpt
, myrpt
->offset
); /* Offset if FM */
6710 if((!res
)&&(myrpt
->rxplon
|| myrpt
->txplon
)){
6712 printf("CTCSS tone freqs.\n");
6713 res
= set_ctcss_freq_ft897(myrpt
, myrpt
->txpl
, myrpt
->rxpl
); /* CTCSS freqs if CTCSS is enabled */
6717 printf("CTCSS mode\n");
6718 res
= set_ctcss_mode_ft897(myrpt
, myrpt
->txplon
, myrpt
->rxplon
); /* CTCSS mode */
6721 if((myrpt
->remmode
== REM_MODE_USB
)||(myrpt
->remmode
== REM_MODE_LSB
)){
6723 printf("Clarifier off\n");
6724 simple_command_ft897(myrpt
, 0x85); /* Clarifier off if LSB or USB */
6729 static int closerem_ft897(struct rpt
*myrpt
)
6731 simple_command_ft897(myrpt
, 0x88); /* PTT off */
6736 * Bump frequency up or down by a small amount
6737 * Return 0 if the new frequnecy is valid, or -1 if invalid
6738 * Interval is in Hz, resolution is 10Hz
6741 static int multimode_bump_freq_ft897(struct rpt
*myrpt
, int interval
)
6744 char mhz
[MAXREMSTR
], decimals
[MAXREMSTR
];
6747 printf("Before bump: %s\n", myrpt
->freq
);
6749 if(split_freq(mhz
, decimals
, myrpt
->freq
))
6755 d
+= (interval
/ 10); /* 10Hz resolution */
6760 else if(d
>= 100000){
6765 if(check_freq_ft897(m
, d
, NULL
)){
6767 printf("Bump freq invalid\n");
6771 snprintf(myrpt
->freq
, MAXREMSTR
, "%d.%05d", m
, d
);
6774 printf("After bump: %s\n", myrpt
->freq
);
6776 return set_freq_ft897(myrpt
, myrpt
->freq
);
6782 * IC-706 I/O handlers
6785 /* Check to see that the frequency is valid */
6786 /* Hard coded limits now, configurable later, maybe? */
6789 static int check_freq_ic706(int m
, int d
, int *defmode
)
6791 int dflmd
= REM_MODE_FM
;
6793 if(m
== 1){ /* 160 meters */
6794 dflmd
= REM_MODE_LSB
;
6798 else if(m
== 3){ /* 80 meters */
6799 dflmd
= REM_MODE_LSB
;
6803 else if(m
== 7){ /* 40 meters */
6804 dflmd
= REM_MODE_LSB
;
6808 else if(m
== 14){ /* 20 meters */
6809 dflmd
= REM_MODE_USB
;
6813 else if(m
== 18){ /* 17 meters */
6814 dflmd
= REM_MODE_USB
;
6815 if((d
< 6800) || (d
> 16800))
6818 else if(m
== 21){ /* 15 meters */
6819 dflmd
= REM_MODE_USB
;
6820 if((d
< 20000) || (d
> 45000))
6823 else if(m
== 24){ /* 12 meters */
6824 dflmd
= REM_MODE_USB
;
6825 if((d
< 89000) || (d
> 99000))
6828 else if(m
== 28){ /* 10 meters */
6829 dflmd
= REM_MODE_USB
;
6833 dflmd
= REM_MODE_FM
;
6835 dflmd
= REM_MODE_USB
;
6839 else if(m
== 50){ /* 6 meters */
6841 dflmd
= REM_MODE_FM
;
6843 dflmd
= REM_MODE_USB
;
6846 else if((m
>= 51) && ( m
< 54)){
6847 dflmd
= REM_MODE_FM
;
6849 else if(m
== 144){ /* 2 meters */
6851 dflmd
= REM_MODE_FM
;
6853 dflmd
= REM_MODE_USB
;
6855 else if((m
>= 145) && (m
< 148)){
6856 dflmd
= REM_MODE_FM
;
6858 else if((m
>= 430) && (m
< 450)){ /* 70 centimeters */
6860 dflmd
= REM_MODE_USB
;
6862 dflmd
= REM_MODE_FM
;
6874 /* take a PL frequency and turn it into a code */
6875 static int ic706_pltocode(char *str
)
6880 s
= strchr(str
,'.');
6882 if (s
) i
= atoi(s
+ 1);
6883 i
+= atoi(str
) * 10;
6990 /* ic-706 simple commands */
6992 static int simple_command_ic706(struct rpt
*myrpt
, char command
, char subcommand
)
6994 unsigned char cmdstr
[10];
6996 cmdstr
[0] = cmdstr
[1] = 0xfe;
6997 cmdstr
[2] = myrpt
->p
.civaddr
;
6999 cmdstr
[4] = command
;
7000 cmdstr
[5] = subcommand
;
7003 return(civ_cmd(myrpt
,cmdstr
,7));
7007 * Set a new frequency for the ic706
7010 static int set_freq_ic706(struct rpt
*myrpt
, char *newfreq
)
7012 unsigned char cmdstr
[20];
7013 char mhz
[MAXREMSTR
], decimals
[MAXREMSTR
];
7018 printf("New frequency: %s\n",newfreq
);
7020 if(split_freq(mhz
, decimals
, newfreq
))
7026 /* The ic-706 likes packed BCD frequencies */
7028 cmdstr
[0] = cmdstr
[1] = 0xfe;
7029 cmdstr
[2] = myrpt
->p
.civaddr
;
7032 cmdstr
[5] = ((d
% 10) << 4);
7033 cmdstr
[6] = (((d
% 1000)/ 100) << 4) + ((d
% 100)/10);
7034 cmdstr
[7] = ((d
/ 10000) << 4) + ((d
% 10000)/1000);
7035 cmdstr
[8] = (((m
% 100)/10) << 4) + (m
% 10);
7036 cmdstr
[9] = (m
/ 100);
7039 return(civ_cmd(myrpt
,cmdstr
,11));
7044 static int set_offset_ic706(struct rpt
*myrpt
, char offset
)
7065 return simple_command_ic706(myrpt
,0x0f,c
);
7071 static int set_mode_ic706(struct rpt
*myrpt
, char newmode
)
7095 return simple_command_ic706(myrpt
,6,c
);
7098 /* Set tone encode and decode modes */
7100 static int set_ctcss_mode_ic706(struct rpt
*myrpt
, char txplon
, char rxplon
)
7102 unsigned char cmdstr
[10];
7105 cmdstr
[0] = cmdstr
[1] = 0xfe;
7106 cmdstr
[2] = myrpt
->p
.civaddr
;
7110 cmdstr
[6] = (txplon
!= 0);
7113 rv
= civ_cmd(myrpt
,cmdstr
,8);
7116 cmdstr
[0] = cmdstr
[1] = 0xfe;
7117 cmdstr
[2] = myrpt
->p
.civaddr
;
7121 cmdstr
[6] = (rxplon
!= 0);
7124 return(civ_cmd(myrpt
,cmdstr
,8));
7128 /* Set transmit and receive ctcss tone frequencies */
7130 static int set_ctcss_freq_ic706(struct rpt
*myrpt
, char *txtone
, char *rxtone
)
7132 unsigned char cmdstr
[10];
7133 char hertz
[MAXREMSTR
],decimal
[MAXREMSTR
];
7136 memset(cmdstr
, 0, 5);
7138 if(split_ctcss_freq(hertz
, decimal
, txtone
))
7144 cmdstr
[0] = cmdstr
[1] = 0xfe;
7145 cmdstr
[2] = myrpt
->p
.civaddr
;
7149 cmdstr
[6] = ((h
/ 100) << 4) + (h
% 100)/ 10;
7150 cmdstr
[7] = ((h
% 10) << 4) + (d
% 10);
7153 rv
= civ_cmd(myrpt
,cmdstr
,9);
7156 if (!rxtone
) return(0);
7158 if(split_ctcss_freq(hertz
, decimal
, rxtone
))
7164 cmdstr
[0] = cmdstr
[1] = 0xfe;
7165 cmdstr
[2] = myrpt
->p
.civaddr
;
7169 cmdstr
[6] = ((h
/ 100) << 4) + (h
% 100)/ 10;
7170 cmdstr
[7] = ((h
% 10) << 4) + (d
% 10);
7172 return(civ_cmd(myrpt
,cmdstr
,9));
7176 static int vfo_ic706(struct rpt
*myrpt
)
7178 unsigned char cmdstr
[10];
7180 cmdstr
[0] = cmdstr
[1] = 0xfe;
7181 cmdstr
[2] = myrpt
->p
.civaddr
;
7186 return(civ_cmd(myrpt
,cmdstr
,6));
7189 static int mem2vfo_ic706(struct rpt
*myrpt
)
7191 unsigned char cmdstr
[10];
7193 cmdstr
[0] = cmdstr
[1] = 0xfe;
7194 cmdstr
[2] = myrpt
->p
.civaddr
;
7199 return(civ_cmd(myrpt
,cmdstr
,6));
7202 static int select_mem_ic706(struct rpt
*myrpt
, int slot
)
7204 unsigned char cmdstr
[10];
7206 cmdstr
[0] = cmdstr
[1] = 0xfe;
7207 cmdstr
[2] = myrpt
->p
.civaddr
;
7211 cmdstr
[6] = ((slot
/ 10) << 4) + (slot
% 10);
7214 return(civ_cmd(myrpt
,cmdstr
,8));
7217 static int set_ic706(struct rpt
*myrpt
)
7222 printf("Set to VFO A\n");
7225 res
= simple_command_ic706(myrpt
,7,0);
7228 if((myrpt
->remmode
== REM_MODE_FM
))
7230 i
= ic706_pltocode(myrpt
->rxpl
);
7231 if (i
== -1) return -1;
7233 printf("Select memory number\n");
7235 res
= select_mem_ic706(myrpt
,i
+ IC706_PL_MEMORY_OFFSET
);
7237 printf("Transfer memory to VFO\n");
7239 res
= mem2vfo_ic706(myrpt
);
7243 printf("Set to VFO\n");
7246 res
= vfo_ic706(myrpt
);
7249 printf("Modulation mode\n");
7252 res
= set_mode_ic706(myrpt
, myrpt
->remmode
); /* Modulation mode */
7255 printf("Split off\n");
7258 simple_command_ic706(myrpt
, 0x82,0); /* Split off */
7261 printf("Frequency\n");
7264 res
= set_freq_ic706(myrpt
, myrpt
->freq
); /* Frequency */
7265 if((myrpt
->remmode
== REM_MODE_FM
)){
7269 res
= set_offset_ic706(myrpt
, myrpt
->offset
); /* Offset if FM */
7272 printf("CTCSS mode\n");
7273 res
= set_ctcss_mode_ic706(myrpt
, myrpt
->txplon
, myrpt
->rxplon
); /* CTCSS mode */
7280 * Bump frequency up or down by a small amount
7281 * Return 0 if the new frequnecy is valid, or -1 if invalid
7282 * Interval is in Hz, resolution is 10Hz
7285 static int multimode_bump_freq_ic706(struct rpt
*myrpt
, int interval
)
7288 char mhz
[MAXREMSTR
], decimals
[MAXREMSTR
];
7289 unsigned char cmdstr
[20];
7292 printf("Before bump: %s\n", myrpt
->freq
);
7294 if(split_freq(mhz
, decimals
, myrpt
->freq
))
7300 d
+= (interval
/ 10); /* 10Hz resolution */
7305 else if(d
>= 100000){
7310 if(check_freq_ic706(m
, d
, NULL
)){
7312 printf("Bump freq invalid\n");
7316 snprintf(myrpt
->freq
, MAXREMSTR
, "%d.%05d", m
, d
);
7319 printf("After bump: %s\n", myrpt
->freq
);
7321 /* The ic-706 likes packed BCD frequencies */
7323 cmdstr
[0] = cmdstr
[1] = 0xfe;
7324 cmdstr
[2] = myrpt
->p
.civaddr
;
7327 cmdstr
[5] = ((d
% 10) << 4);
7328 cmdstr
[6] = (((d
% 1000)/ 100) << 4) + ((d
% 100)/10);
7329 cmdstr
[7] = ((d
/ 10000) << 4) + ((d
% 10000)/1000);
7330 cmdstr
[8] = (((m
% 100)/10) << 4) + (m
% 10);
7331 cmdstr
[9] = (m
/ 100);
7334 return(serial_remote_io(myrpt
,cmdstr
,11,NULL
,0,0));
7340 * Dispatch to correct I/O handler
7343 static int setrem(struct rpt
*myrpt
)
7346 char *offsets
[] = {"MINUS","SIMPLEX","PLUS"};
7347 char *powerlevels
[] = {"LOW","MEDIUM","HIGH"};
7348 char *modes
[] = {"FM","USB","LSB","AM"};
7351 if (myrpt
->p
.archivedir
)
7353 sprintf(str
,"FREQ,%s,%s,%s,%s,%s,%s,%d,%d",myrpt
->freq
,
7354 modes
[(int)myrpt
->remmode
],
7355 myrpt
->txpl
,myrpt
->rxpl
,offsets
[(int)myrpt
->offset
],
7356 powerlevels
[(int)myrpt
->powerlevel
],myrpt
->txplon
,
7358 donodelog(myrpt
,str
);
7360 if(!strcmp(myrpt
->remote
, remote_rig_ft897
))
7362 rpt_telemetry(myrpt
,SETREMOTE
,NULL
);
7365 if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
7367 rpt_telemetry(myrpt
,SETREMOTE
,NULL
);
7370 else if(!strcmp(myrpt
->remote
, remote_rig_rbi
))
7372 res
= setrbi_check(myrpt
);
7375 rpt_telemetry(myrpt
,SETREMOTE
,NULL
);
7379 else if(!strcmp(myrpt
->remote
, remote_rig_kenwood
)) {
7380 rpt_telemetry(myrpt
,SETREMOTE
,NULL
);
7386 if (res
< 0) ast_log(LOG_ERROR
,"Unable to send remote command on node %s\n",myrpt
->name
);
7391 static int closerem(struct rpt
*myrpt
)
7393 if(!strcmp(myrpt
->remote
, remote_rig_ft897
))
7394 return closerem_ft897(myrpt
);
7400 * Dispatch to correct RX frequency checker
7403 static int check_freq(struct rpt
*myrpt
, int m
, int d
, int *defmode
)
7405 if(!strcmp(myrpt
->remote
, remote_rig_ft897
))
7406 return check_freq_ft897(m
, d
, defmode
);
7407 else if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
7408 return check_freq_ic706(m
, d
, defmode
);
7409 else if(!strcmp(myrpt
->remote
, remote_rig_rbi
))
7410 return check_freq_rbi(m
, d
, defmode
);
7411 else if(!strcmp(myrpt
->remote
, remote_rig_kenwood
))
7412 return check_freq_kenwood(m
, d
, defmode
);
7418 * Check TX frequency before transmitting
7421 static char check_tx_freq(struct rpt
*myrpt
)
7424 int radio_mhz
, radio_decimals
, ulimit_mhz
, ulimit_decimals
, llimit_mhz
, llimit_decimals
;
7425 char radio_mhz_char
[MAXREMSTR
];
7426 char radio_decimals_char
[MAXREMSTR
];
7427 char limit_mhz_char
[MAXREMSTR
];
7428 char limit_decimals_char
[MAXREMSTR
];
7430 char *limit_ranges
[40];
7431 struct ast_variable
*limitlist
;
7434 /* Must have user logged in and tx_limits defined */
7436 if(!myrpt
->p
.txlimitsstanzaname
|| !myrpt
->loginuser
[0] || !myrpt
->loginlevel
[0]){
7438 ast_log(LOG_NOTICE
, "No tx band table defined, or no user logged in\n");
7440 return 1; /* Assume it's ok otherwise */
7443 /* Retrieve the band table for the loginlevel */
7444 limitlist
= ast_variable_browse(myrpt
->cfg
, myrpt
->p
.txlimitsstanzaname
);
7447 ast_log(LOG_WARNING
, "No entries in %s band table stanza\n", myrpt
->p
.txlimitsstanzaname
);
7451 split_freq(radio_mhz_char
, radio_decimals_char
, myrpt
->freq
);
7452 radio_mhz
= atoi(radio_mhz_char
);
7453 radio_decimals
= decimals2int(radio_decimals_char
);
7457 ast_log(LOG_NOTICE
, "Login User = %s, login level = %s\n", myrpt
->loginuser
, myrpt
->loginlevel
);
7460 /* Find our entry */
7462 for(;limitlist
; limitlist
=limitlist
->next
){
7463 if(!strcmp(limitlist
->name
, myrpt
->loginlevel
))
7468 ast_log(LOG_WARNING
, "Can't find %s entry in band table stanza %s\n", myrpt
->loginlevel
, myrpt
->p
.txlimitsstanzaname
);
7473 ast_log(LOG_NOTICE
, "Auth %s = %s\n", limitlist
->name
, limitlist
->value
);
7476 /* Parse the limits */
7478 strncpy(limits
, limitlist
->value
, 256);
7480 finddelim(limits
, limit_ranges
, 40);
7481 for(i
= 0; i
< 40 && limit_ranges
[i
] ; i
++){
7484 strncpy(range
, limit_ranges
[i
], 40);
7487 ast_log(LOG_NOTICE
, "Checking to see if %s is within limits of %s\n", myrpt
->freq
, range
);
7490 r
= strchr(range
, '-');
7492 ast_log(LOG_WARNING
, "Malformed range in %s tx band table entry\n", limitlist
->name
);
7496 s
= eatwhite(range
);
7498 split_freq(limit_mhz_char
, limit_decimals_char
, s
);
7499 llimit_mhz
= atoi(limit_mhz_char
);
7500 llimit_decimals
= decimals2int(limit_decimals_char
);
7501 split_freq(limit_mhz_char
, limit_decimals_char
, r
);
7502 ulimit_mhz
= atoi(limit_mhz_char
);
7503 ulimit_decimals
= decimals2int(limit_decimals_char
);
7505 if((radio_mhz
>= llimit_mhz
) && (radio_mhz
<= ulimit_mhz
)){
7506 if(radio_mhz
== llimit_mhz
){ /* CASE 1: TX freq is in llimit mhz portion of band */
7507 if(radio_decimals
>= llimit_decimals
){ /* Cannot be below llimit decimals */
7508 if(llimit_mhz
== ulimit_mhz
){ /* If bandwidth < 1Mhz, check ulimit decimals */
7509 if(radio_decimals
<= ulimit_decimals
){
7514 ast_log(LOG_NOTICE
, "Invalid TX frequency, debug msg 1\n");
7522 else{ /* Is below llimit decimals */
7524 ast_log(LOG_NOTICE
, "Invalid TX frequency, debug msg 2\n");
7528 else if(radio_mhz
== ulimit_mhz
){ /* CASE 2: TX freq not in llimit mhz portion of band */
7529 if(radio_decimals
<= ulimit_decimals
){
7532 else{ /* Is above ulimit decimals */
7534 ast_log(LOG_NOTICE
, "Invalid TX frequency, debug msg 3\n");
7538 else /* CASE 3: TX freq within a multi-Mhz band and ok */
7542 if(debug
> 3) /* No match found in TX band table */
7543 ast_log(LOG_NOTICE
, "Invalid TX frequency, debug msg 4\n");
7549 * Dispatch to correct frequency bumping function
7552 static int multimode_bump_freq(struct rpt
*myrpt
, int interval
)
7554 if(!strcmp(myrpt
->remote
, remote_rig_ft897
))
7555 return multimode_bump_freq_ft897(myrpt
, interval
);
7556 else if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
7557 return multimode_bump_freq_ic706(myrpt
, interval
);
7564 * Queue announcment that scan has been stopped
7567 static void stop_scan(struct rpt
*myrpt
)
7569 myrpt
->hfscanstop
= 1;
7570 rpt_telemetry(myrpt
,SCAN
,0);
7574 * This is called periodically when in scan mode
7578 static int service_scan(struct rpt
*myrpt
)
7581 char mhz
[MAXREMSTR
], decimals
[MAXREMSTR
], k10
=0i
, k100
=0;
7583 switch(myrpt
->hfscanmode
){
7585 case HF_SCAN_DOWN_SLOW
:
7586 interval
= -10; /* 100Hz /sec */
7589 case HF_SCAN_DOWN_QUICK
:
7590 interval
= -50; /* 500Hz /sec */
7593 case HF_SCAN_DOWN_FAST
:
7594 interval
= -200; /* 2KHz /sec */
7597 case HF_SCAN_UP_SLOW
:
7598 interval
= 10; /* 100Hz /sec */
7601 case HF_SCAN_UP_QUICK
:
7602 interval
= 50; /* 500 Hz/sec */
7605 case HF_SCAN_UP_FAST
:
7606 interval
= 200; /* 2KHz /sec */
7610 myrpt
->hfscanmode
= 0; /* Huh? */
7614 res
= split_freq(mhz
, decimals
, myrpt
->freq
);
7619 res
= multimode_bump_freq(myrpt
, interval
);
7623 res
= split_freq(mhz
, decimals
, myrpt
->freq
);
7627 myrpt
->hfscanmode
= 0;
7628 myrpt
->hfscanstatus
= -2;
7632 /* Announce 10KHz boundaries */
7633 if(k10
!= decimals
[1]){
7634 int myhund
= (interval
< 0) ? k100
: decimals
[0];
7635 int myten
= (interval
< 0) ? k10
: decimals
[1];
7636 myrpt
->hfscanstatus
= (myten
== '0') ? (myhund
- '0') * 100 : (myten
- '0') * 10;
7637 } else myrpt
->hfscanstatus
= 0;
7643 * Retrieve a memory channel
7644 * Return 0 if sucessful,
7645 * -1 if channel not found,
7649 static int retreive_memory(struct rpt
*myrpt
, char *memory
)
7651 char tmp
[30], *s
, *s1
, *val
;
7653 val
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->p
.memory
, memory
);
7657 strncpy(tmp
,val
,sizeof(tmp
) - 1);
7658 tmp
[sizeof(tmp
)-1] = 0;
7660 s
= strchr(tmp
,',');
7668 strncpy(myrpt
->freq
, tmp
, sizeof(myrpt
->freq
) - 1);
7669 strncpy(myrpt
->rxpl
, s
, sizeof(myrpt
->rxpl
) - 1);
7670 strncpy(myrpt
->txpl
, s
, sizeof(myrpt
->rxpl
) - 1);
7671 myrpt
->remmode
= REM_MODE_FM
;
7672 myrpt
->offset
= REM_SIMPLEX
;
7673 myrpt
->powerlevel
= REM_MEDPWR
;
7674 myrpt
->txplon
= myrpt
->rxplon
= 0;
7679 strcpy(myrpt
->rxpl
, "100.0");
7680 strcpy(myrpt
->txpl
, "100.0");
7681 myrpt
->remmode
= REM_MODE_AM
;
7685 strcpy(myrpt
->rxpl
, "100.0");
7686 strcpy(myrpt
->txpl
, "100.0");
7687 myrpt
->remmode
= REM_MODE_LSB
;
7690 myrpt
->remmode
= REM_MODE_FM
;
7694 myrpt
->powerlevel
= REM_LOWPWR
;
7698 myrpt
->powerlevel
= REM_HIPWR
;
7703 myrpt
->powerlevel
= REM_MEDPWR
;
7707 myrpt
->offset
= REM_MINUS
;
7711 myrpt
->offset
= REM_PLUS
;
7716 myrpt
->offset
= REM_SIMPLEX
;
7731 strcpy(myrpt
->rxpl
, "100.0");
7732 strcpy(myrpt
->txpl
, "100.0");
7733 myrpt
->remmode
= REM_MODE_USB
;
7745 * Remote base function
7748 static int function_remote(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
7751 int i
,j
,p
,r
,ht
,k
,l
,ls2
,m
,d
,offset
,offsave
, modesave
, defmode
;
7753 char oc
,*cp
,*cp1
,*cp2
;
7754 char tmp
[20], freq
[20] = "", savestr
[20] = "";
7755 char mhz
[MAXREMSTR
], decimals
[MAXREMSTR
];
7757 if((!param
) || (command_source
== SOURCE_RPT
) || (command_source
== SOURCE_LNK
))
7762 if ((p
!= 99) && (p
!= 5) && (p
!= 140) && myrpt
->p
.authlevel
&&
7763 (!myrpt
->loginlevel
[0])) return DC_ERROR
;
7764 multimode
= multimode_capable(myrpt
);
7768 case 1: /* retrieve memory */
7769 if(strlen(digitbuf
) < 2) /* needs 2 digits */
7772 for(i
= 0 ; i
< 2 ; i
++){
7773 if((digitbuf
[i
] < '0') || (digitbuf
[i
] > '9'))
7777 r
= retreive_memory(myrpt
, digitbuf
);
7779 rpt_telemetry(myrpt
,MEMNOTFOUND
,NULL
);
7785 if (setrem(myrpt
) == -1) return DC_ERROR
;
7788 case 2: /* set freq and offset */
7791 for(i
= 0, j
= 0, k
= 0, l
= 0 ; digitbuf
[i
] ; i
++){ /* look for M+*K+*O or M+*H+* depending on mode */
7792 if(digitbuf
[i
] == '*'){
7796 if((digitbuf
[i
] < '0') || (digitbuf
[i
] > '9'))
7800 l
++; /* # of digits before first * */
7802 k
++; /* # of digits after first * */
7806 i
= strlen(digitbuf
) - 1;
7808 if((j
> 2) || (l
> 3) || (k
> 6))
7809 goto invalid_freq
; /* &^@#! */
7812 if((j
> 2) || (l
> 4) || (k
> 3))
7813 goto invalid_freq
; /* &^@#! */
7816 /* Wait for M+*K+* */
7819 break; /* Not yet */
7821 /* We have a frequency */
7823 strncpy(tmp
, digitbuf
,sizeof(tmp
) - 1);
7826 s1
= strsep(&s
, "*"); /* Pick off MHz */
7827 s2
= strsep(&s
,"*"); /* Pick off KHz and Hz */
7830 switch(ls2
){ /* Allow partial entry of khz and hz digits for laziness support */
7843 if((s2
[2] != '0')&&(s2
[2] != '5'))
7851 ht
= 10 * (atoi(s2
+(ls2
-1)));
7856 ht
= (atoi(s2
+(ls2
-2)));
7863 /* Check frequency for validity and establish a default mode */
7865 snprintf(freq
, sizeof(freq
), "%s.%03d%02d",s1
, k
, ht
);
7868 printf("New frequency: %s\n", freq
);
7870 split_freq(mhz
, decimals
, freq
);
7874 if(check_freq(myrpt
, m
, d
, &defmode
)) /* Check to see if frequency entered is legit */
7878 if((defmode
== REM_MODE_FM
) && (digitbuf
[i
] == '*')) /* If FM, user must enter and additional offset digit */
7879 break; /* Not yet */
7882 offset
= REM_SIMPLEX
; /* Assume simplex */
7884 if(defmode
== REM_MODE_FM
){
7885 oc
= *s
; /* Pick off offset */
7894 offset
= REM_SIMPLEX
;
7906 offsave
= myrpt
->offset
;
7907 modesave
= myrpt
->remmode
;
7908 strncpy(savestr
, myrpt
->freq
, sizeof(savestr
) - 1);
7909 strncpy(myrpt
->freq
, freq
, sizeof(myrpt
->freq
) - 1);
7910 myrpt
->offset
= offset
;
7911 myrpt
->remmode
= defmode
;
7913 if (setrem(myrpt
) == -1){
7914 myrpt
->offset
= offsave
;
7915 myrpt
->remmode
= modesave
;
7916 strncpy(myrpt
->freq
, savestr
, sizeof(myrpt
->freq
) - 1);
7923 rpt_telemetry(myrpt
,INVFREQ
,NULL
);
7926 case 3: /* set rx PL tone */
7927 for(i
= 0, j
= 0, k
= 0, l
= 0 ; digitbuf
[i
] ; i
++){ /* look for N+*N */
7928 if(digitbuf
[i
] == '*'){
7932 if((digitbuf
[i
] < '0') || (digitbuf
[i
] > '9'))
7941 if((j
> 1) || (k
> 3) || (l
> 1))
7942 return DC_ERROR
; /* &$@^! */
7943 i
= strlen(digitbuf
) - 1;
7944 if((j
!= 1) || (k
< 2)|| (l
!= 1))
7945 break; /* Not yet */
7947 printf("PL digits entered %s\n", digitbuf
);
7949 strncpy(tmp
, digitbuf
, sizeof(tmp
) - 1);
7950 /* see if we have at least 1 */
7951 s
= strchr(tmp
,'*');
7954 strncpy(savestr
, myrpt
->rxpl
, sizeof(savestr
) - 1);
7955 strncpy(myrpt
->rxpl
, tmp
, sizeof(myrpt
->rxpl
) - 1);
7956 if(!strcmp(myrpt
->remote
, remote_rig_rbi
))
7958 strncpy(myrpt
->txpl
, tmp
, sizeof(myrpt
->txpl
) - 1);
7960 if (setrem(myrpt
) == -1){
7961 strncpy(myrpt
->rxpl
, savestr
, sizeof(myrpt
->rxpl
) - 1);
7968 case 4: /* set tx PL tone */
7969 /* cant set tx tone on RBI (rx tone does both) */
7970 if(!strcmp(myrpt
->remote
, remote_rig_rbi
))
7972 if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
7974 for(i
= 0, j
= 0, k
= 0, l
= 0 ; digitbuf
[i
] ; i
++){ /* look for N+*N */
7975 if(digitbuf
[i
] == '*'){
7979 if((digitbuf
[i
] < '0') || (digitbuf
[i
] > '9'))
7988 if((j
> 1) || (k
> 3) || (l
> 1))
7989 return DC_ERROR
; /* &$@^! */
7990 i
= strlen(digitbuf
) - 1;
7991 if((j
!= 1) || (k
< 2)|| (l
!= 1))
7992 break; /* Not yet */
7994 printf("PL digits entered %s\n", digitbuf
);
7996 strncpy(tmp
, digitbuf
, sizeof(tmp
) - 1);
7997 /* see if we have at least 1 */
7998 s
= strchr(tmp
,'*');
8001 strncpy(savestr
, myrpt
->txpl
, sizeof(savestr
) - 1);
8002 strncpy(myrpt
->txpl
, tmp
, sizeof(myrpt
->txpl
) - 1);
8004 if (setrem(myrpt
) == -1){
8005 strncpy(myrpt
->txpl
, savestr
, sizeof(myrpt
->txpl
) - 1);
8013 case 6: /* MODE (FM,USB,LSB,AM) */
8014 if(strlen(digitbuf
) < 1)
8018 return DC_ERROR
; /* Multimode radios only */
8022 split_freq(mhz
, decimals
, myrpt
->freq
);
8024 if(m
< 29) /* No FM allowed below 29MHz! */
8026 myrpt
->remmode
= REM_MODE_FM
;
8028 rpt_telemetry(myrpt
,REMMODE
,NULL
);
8032 myrpt
->remmode
= REM_MODE_USB
;
8033 rpt_telemetry(myrpt
,REMMODE
,NULL
);
8037 myrpt
->remmode
= REM_MODE_LSB
;
8038 rpt_telemetry(myrpt
,REMMODE
,NULL
);
8042 myrpt
->remmode
= REM_MODE_AM
;
8043 rpt_telemetry(myrpt
,REMMODE
,NULL
);
8052 return DC_COMPLETEQUIET
;
8054 /* cant log in when logged in */
8055 if (myrpt
->loginlevel
[0])
8057 *myrpt
->loginuser
= 0;
8058 myrpt
->loginlevel
[0] = 0;
8060 cp1
= strchr(cp
,',');
8061 ast_mutex_lock(&myrpt
->lock
);
8065 cp2
= strchr(cp1
+ 1,',');
8069 strncpy(myrpt
->loginlevel
,cp2
+ 1,
8070 sizeof(myrpt
->loginlevel
) - 1);
8072 strncpy(myrpt
->loginuser
,cp1
+ 1,sizeof(myrpt
->loginuser
));
8073 ast_mutex_unlock(&myrpt
->lock
);
8074 if (myrpt
->p
.archivedir
)
8078 sprintf(str
,"LOGIN,%s,%s",
8079 myrpt
->loginuser
,myrpt
->loginlevel
);
8080 donodelog(myrpt
,str
);
8083 printf("loginuser %s level %s\n",myrpt
->loginuser
,myrpt
->loginlevel
);
8084 rpt_telemetry(myrpt
,REMLOGIN
,NULL
);
8087 return DC_COMPLETEQUIET
;
8088 case 100: /* RX PL Off */
8091 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8092 return DC_COMPLETEQUIET
;
8093 case 101: /* RX PL On */
8096 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8097 return DC_COMPLETEQUIET
;
8098 case 102: /* TX PL Off */
8101 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8102 return DC_COMPLETEQUIET
;
8103 case 103: /* TX PL On */
8106 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8107 return DC_COMPLETEQUIET
;
8108 case 104: /* Low Power */
8109 if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
8111 myrpt
->powerlevel
= REM_LOWPWR
;
8113 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8114 return DC_COMPLETEQUIET
;
8115 case 105: /* Medium Power */
8116 if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
8118 myrpt
->powerlevel
= REM_MEDPWR
;
8120 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8121 return DC_COMPLETEQUIET
;
8122 case 106: /* Hi Power */
8123 if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
8125 myrpt
->powerlevel
= REM_HIPWR
;
8127 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8128 return DC_COMPLETEQUIET
;
8129 case 107: /* Bump down 20Hz */
8130 multimode_bump_freq(myrpt
, -20);
8132 case 108: /* Bump down 100Hz */
8133 multimode_bump_freq(myrpt
, -100);
8135 case 109: /* Bump down 500Hz */
8136 multimode_bump_freq(myrpt
, -500);
8138 case 110: /* Bump up 20Hz */
8139 multimode_bump_freq(myrpt
, 20);
8141 case 111: /* Bump up 100Hz */
8142 multimode_bump_freq(myrpt
, 100);
8144 case 112: /* Bump up 500Hz */
8145 multimode_bump_freq(myrpt
, 500);
8147 case 113: /* Scan down slow */
8148 myrpt
->scantimer
= REM_SCANTIME
;
8149 myrpt
->hfscanmode
= HF_SCAN_DOWN_SLOW
;
8150 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8151 return DC_COMPLETEQUIET
;
8152 case 114: /* Scan down quick */
8153 myrpt
->scantimer
= REM_SCANTIME
;
8154 myrpt
->hfscanmode
= HF_SCAN_DOWN_QUICK
;
8155 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8156 return DC_COMPLETEQUIET
;
8157 case 115: /* Scan down fast */
8158 myrpt
->scantimer
= REM_SCANTIME
;
8159 myrpt
->hfscanmode
= HF_SCAN_DOWN_FAST
;
8160 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8161 return DC_COMPLETEQUIET
;
8162 case 116: /* Scan up slow */
8163 myrpt
->scantimer
= REM_SCANTIME
;
8164 myrpt
->hfscanmode
= HF_SCAN_UP_SLOW
;
8165 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8166 return DC_COMPLETEQUIET
;
8167 case 117: /* Scan up quick */
8168 myrpt
->scantimer
= REM_SCANTIME
;
8169 myrpt
->hfscanmode
= HF_SCAN_UP_QUICK
;
8170 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8171 return DC_COMPLETEQUIET
;
8172 case 118: /* Scan up fast */
8173 myrpt
->scantimer
= REM_SCANTIME
;
8174 myrpt
->hfscanmode
= HF_SCAN_UP_FAST
;
8175 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8176 return DC_COMPLETEQUIET
;
8177 case 119: /* Tune Request */
8178 /* if not currently going, and valid to do */
8179 if((!myrpt
->tunerequest
) &&
8180 ((!strcmp(myrpt
->remote
, remote_rig_ft897
) ||
8181 !strcmp(myrpt
->remote
, remote_rig_ic706
)) )) {
8182 myrpt
->remotetx
= 0;
8183 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_UNKEY
);
8184 myrpt
->tunerequest
= 1;
8185 rpt_telemetry(myrpt
,TUNE
,NULL
);
8186 return DC_COMPLETEQUIET
;
8189 case 5: /* Long Status */
8190 rpt_telemetry(myrpt
,REMLONGSTATUS
,NULL
);
8191 return DC_COMPLETEQUIET
;
8192 case 140: /* Short Status */
8193 rpt_telemetry(myrpt
,REMSHORTSTATUS
,NULL
);
8194 return DC_COMPLETEQUIET
;
8211 do_dtmf_local(myrpt
,remdtmfstr
[p
- 200]);
8212 return DC_COMPLETEQUIET
;
8216 return DC_INDETERMINATE
;
8220 static int handle_remote_dtmf_digit(struct rpt
*myrpt
,char c
, char *keyed
, int phonemode
)
8223 int ret
,res
= 0,src
;
8225 time(&myrpt
->last_activity_time
);
8226 /* Stop scan mode if in scan mode */
8227 if(myrpt
->hfscanmode
){
8234 if ((myrpt
->dtmf_time_rem
+ DTMF_TIMEOUT
) < now
)
8236 myrpt
->dtmfidx
= -1;
8237 myrpt
->dtmfbuf
[0] = 0;
8238 myrpt
->dtmf_time_rem
= 0;
8240 /* if decode not active */
8241 if (myrpt
->dtmfidx
== -1)
8243 /* if not lead-in digit, dont worry */
8244 if (c
!= myrpt
->p
.funcchar
)
8246 if (!myrpt
->p
.propagate_dtmf
)
8248 rpt_mutex_lock(&myrpt
->lock
);
8249 do_dtmf_local(myrpt
,c
);
8250 rpt_mutex_unlock(&myrpt
->lock
);
8255 myrpt
->dtmfbuf
[0] = 0;
8256 myrpt
->dtmf_time_rem
= now
;
8259 /* if too many in buffer, start over */
8260 if (myrpt
->dtmfidx
>= MAXDTMF
)
8263 myrpt
->dtmfbuf
[0] = 0;
8264 myrpt
->dtmf_time_rem
= now
;
8266 if (c
== myrpt
->p
.funcchar
)
8268 /* if star at beginning, or 2 together, erase buffer */
8269 if ((myrpt
->dtmfidx
< 1) ||
8270 (myrpt
->dtmfbuf
[myrpt
->dtmfidx
- 1] == myrpt
->p
.funcchar
))
8273 myrpt
->dtmfbuf
[0] = 0;
8274 myrpt
->dtmf_time_rem
= now
;
8278 myrpt
->dtmfbuf
[myrpt
->dtmfidx
++] = c
;
8279 myrpt
->dtmfbuf
[myrpt
->dtmfidx
] = 0;
8280 myrpt
->dtmf_time_rem
= now
;
8284 if (phonemode
> 1) src
= SOURCE_DPHONE
;
8285 else if (phonemode
) src
= SOURCE_PHONE
;
8286 ret
= collect_function_digits(myrpt
, myrpt
->dtmfbuf
, src
, NULL
);
8290 case DC_INDETERMINATE
:
8295 if (keyed
) *keyed
= 1;
8301 myrpt
->dtmfbuf
[0] = 0;
8308 case DC_COMPLETEQUIET
:
8309 myrpt
->totalexecdcommands
++;
8310 myrpt
->dailyexecdcommands
++;
8311 strncpy(myrpt
->lastdtmfcommand
, myrpt
->dtmfbuf
, MAXDTMF
-1);
8312 myrpt
->lastdtmfcommand
[MAXDTMF
-1] = '\0';
8313 myrpt
->dtmfbuf
[0] = 0;
8314 myrpt
->dtmfidx
= -1;
8315 myrpt
->dtmf_time_rem
= 0;
8320 myrpt
->dtmfbuf
[0] = 0;
8321 myrpt
->dtmfidx
= -1;
8322 myrpt
->dtmf_time_rem
= 0;
8330 static int handle_remote_data(struct rpt
*myrpt
, char *str
)
8332 char tmp
[300],cmd
[300],dest
[300],src
[300],c
;
8335 /* put string in our buffer */
8336 strncpy(tmp
,str
,sizeof(tmp
) - 1);
8337 if (!strcmp(tmp
,discstr
)) return 0;
8339 #ifndef DO_NOT_NOTIFY_MDC1200_ON_REMOTE_BASES
8342 if (sscanf(tmp
,"%s %s %x",cmd
,src
,&seq
) != 3)
8344 ast_log(LOG_WARNING
, "Unable to parse ident string %s\n",str
);
8347 mdc1200_notify(myrpt
,src
,seq
);
8351 if (sscanf(tmp
,"%s %s %s %d %c",cmd
,dest
,src
,&seq
,&c
) != 5)
8353 ast_log(LOG_WARNING
, "Unable to parse link string %s\n",str
);
8356 if (strcmp(cmd
,"D"))
8358 ast_log(LOG_WARNING
, "Unable to parse link string %s\n",str
);
8361 /* if not for me, ignore */
8362 if (strcmp(dest
,myrpt
->name
)) return 0;
8363 if (myrpt
->p
.archivedir
)
8367 sprintf(str
,"DTMF,%c",c
);
8368 donodelog(myrpt
,str
);
8370 c
= func_xlat(myrpt
,c
,&myrpt
->p
.outxlat
);
8372 res
= handle_remote_dtmf_digit(myrpt
,c
, NULL
, 0);
8375 rpt_telemetry(myrpt
,COMPLETE
,NULL
);
8379 static int handle_remote_phone_dtmf(struct rpt
*myrpt
, char c
, char *keyed
, int phonemode
)
8384 if (keyed
&& *keyed
&& (c
== myrpt
->p
.endchar
))
8387 return DC_INDETERMINATE
;
8390 if (myrpt
->p
.archivedir
)
8394 sprintf(str
,"DTMF(P),%c",c
);
8395 donodelog(myrpt
,str
);
8397 res
= handle_remote_dtmf_digit(myrpt
,c
,keyed
, phonemode
);
8400 rpt_telemetry(myrpt
,COMPLETE
,NULL
);
8404 static int attempt_reconnect(struct rpt
*myrpt
, struct rpt_link
*l
)
8406 char *val
, *s
, *s1
, *s2
, *tele
;
8407 char tmp
[300], deststr
[300] = "";
8409 val
= node_lookup(myrpt
,l
->name
);
8412 fprintf(stderr
,"attempt_reconnect: cannot find node %s\n",l
->name
);
8416 rpt_mutex_lock(&myrpt
->lock
);
8417 /* remove from queue */
8418 remque((struct qelem
*) l
);
8419 rpt_mutex_unlock(&myrpt
->lock
);
8420 strncpy(tmp
,val
,sizeof(tmp
) - 1);
8422 s1
= strsep(&s
,",");
8423 s2
= strsep(&s
,",");
8424 snprintf(deststr
, sizeof(deststr
), "IAX2/%s", s1
);
8425 tele
= strchr(deststr
, '/');
8427 fprintf(stderr
,"attempt_reconnect:Dial number (%s) must be in format tech/number\n",deststr
);
8433 l
->thisconnected
= 0;
8434 l
->chan
= ast_request(deststr
, AST_FORMAT_SLINEAR
, tele
,NULL
);
8436 ast_set_read_format(l
->chan
, AST_FORMAT_SLINEAR
);
8437 ast_set_write_format(l
->chan
, AST_FORMAT_SLINEAR
);
8438 l
->chan
->whentohangup
= 0;
8439 l
->chan
->appl
= "Apprpt";
8440 l
->chan
->data
= "(Remote Rx)";
8441 if (option_verbose
> 2)
8442 ast_verbose(VERBOSE_PREFIX_3
"rpt (attempt_reconnect) initiating call to %s/%s on %s\n",
8443 deststr
, tele
, l
->chan
->name
);
8444 if(l
->chan
->cid
.cid_num
)
8445 free(l
->chan
->cid
.cid_num
);
8446 l
->chan
->cid
.cid_num
= strdup(myrpt
->name
);
8447 ast_call(l
->chan
,tele
,999);
8452 if (option_verbose
> 2)
8453 ast_verbose(VERBOSE_PREFIX_3
"Unable to place call to %s/%s on %s\n",
8454 deststr
,tele
,l
->chan
->name
);
8457 rpt_mutex_lock(&myrpt
->lock
);
8458 /* put back in queue */
8459 insque((struct qelem
*)l
,(struct qelem
*)myrpt
->links
.next
);
8460 rpt_mutex_unlock(&myrpt
->lock
);
8461 ast_log(LOG_NOTICE
,"Reconnect Attempt to %s in process\n",l
->name
);
8465 /* 0 return=continue, 1 return = break, -1 return = error */
8466 static void local_dtmf_helper(struct rpt
*myrpt
,char c
)
8469 pthread_attr_t attr
;
8470 char cmd
[MAXDTMF
+1] = "";
8472 if (myrpt
->p
.archivedir
)
8476 sprintf(str
,"DTMF,MAIN,%c",c
);
8477 donodelog(myrpt
,str
);
8479 if (c
== myrpt
->p
.endchar
)
8481 /* if in simple mode, kill autopatch */
8482 if (myrpt
->p
.simple
&& myrpt
->callmode
)
8484 rpt_mutex_lock(&myrpt
->lock
);
8485 myrpt
->callmode
= 0;
8486 rpt_mutex_unlock(&myrpt
->lock
);
8487 rpt_telemetry(myrpt
,TERM
,NULL
);
8490 rpt_mutex_lock(&myrpt
->lock
);
8492 if (myrpt
->cmdnode
[0])
8494 myrpt
->cmdnode
[0] = 0;
8495 myrpt
->dtmfidx
= -1;
8496 myrpt
->dtmfbuf
[0] = 0;
8497 rpt_mutex_unlock(&myrpt
->lock
);
8498 rpt_telemetry(myrpt
,COMPLETE
,NULL
);
8502 rpt_mutex_unlock(&myrpt
->lock
);
8503 if (myrpt
->p
.propagate_phonedtmf
)
8504 do_dtmf_phone(myrpt
,NULL
,c
);
8508 rpt_mutex_lock(&myrpt
->lock
);
8509 if (myrpt
->cmdnode
[0])
8511 rpt_mutex_unlock(&myrpt
->lock
);
8512 send_link_dtmf(myrpt
,c
);
8515 if (!myrpt
->p
.simple
)
8517 if (c
== myrpt
->p
.funcchar
)
8520 myrpt
->dtmfbuf
[myrpt
->dtmfidx
] = 0;
8521 rpt_mutex_unlock(&myrpt
->lock
);
8522 time(&myrpt
->dtmf_time
);
8525 else if ((c
!= myrpt
->p
.endchar
) && (myrpt
->dtmfidx
>= 0))
8527 time(&myrpt
->dtmf_time
);
8529 if (myrpt
->dtmfidx
< MAXDTMF
)
8531 myrpt
->dtmfbuf
[myrpt
->dtmfidx
++] = c
;
8532 myrpt
->dtmfbuf
[myrpt
->dtmfidx
] = 0;
8534 strncpy(cmd
, myrpt
->dtmfbuf
, sizeof(cmd
) - 1);
8536 rpt_mutex_unlock(&myrpt
->lock
);
8537 res
= collect_function_digits(myrpt
, cmd
, SOURCE_RPT
, NULL
);
8538 rpt_mutex_lock(&myrpt
->lock
);
8540 case DC_INDETERMINATE
:
8544 myrpt
->dtmfbuf
[0] = 0;
8547 case DC_COMPLETEQUIET
:
8548 myrpt
->totalexecdcommands
++;
8549 myrpt
->dailyexecdcommands
++;
8550 strncpy(myrpt
->lastdtmfcommand
, cmd
, MAXDTMF
-1);
8551 myrpt
->lastdtmfcommand
[MAXDTMF
-1] = '\0';
8552 myrpt
->dtmfbuf
[0] = 0;
8553 myrpt
->dtmfidx
= -1;
8554 myrpt
->dtmf_time
= 0;
8559 myrpt
->dtmfbuf
[0] = 0;
8560 myrpt
->dtmfidx
= -1;
8561 myrpt
->dtmf_time
= 0;
8564 if(res
!= DC_INDETERMINATE
) {
8565 rpt_mutex_unlock(&myrpt
->lock
);
8571 else /* if simple */
8573 if ((!myrpt
->callmode
) && (c
== myrpt
->p
.funcchar
))
8575 myrpt
->callmode
= 1;
8576 myrpt
->patchnoct
= 0;
8577 myrpt
->patchquiet
= 0;
8578 myrpt
->patchfarenddisconnect
= 0;
8579 myrpt
->patchdialtime
= 0;
8580 strncpy(myrpt
->patchcontext
, myrpt
->p
.ourcontext
, MAXPATCHCONTEXT
);
8582 myrpt
->exten
[myrpt
->cidx
] = 0;
8583 rpt_mutex_unlock(&myrpt
->lock
);
8584 pthread_attr_init(&attr
);
8585 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
8586 ast_pthread_create(&myrpt
->rpt_call_thread
,&attr
,rpt_call
,(void *)myrpt
);
8590 if (myrpt
->callmode
== 1)
8592 myrpt
->exten
[myrpt
->cidx
++] = c
;
8593 myrpt
->exten
[myrpt
->cidx
] = 0;
8594 /* if this exists */
8595 if (ast_exists_extension(myrpt
->pchannel
,myrpt
->patchcontext
,myrpt
->exten
,1,NULL
))
8597 myrpt
->callmode
= 2;
8598 rpt_mutex_unlock(&myrpt
->lock
);
8599 if(!myrpt
->patchquiet
)
8600 rpt_telemetry(myrpt
,PROC
,NULL
);
8603 /* if can continue, do so */
8604 if (!ast_canmatch_extension(myrpt
->pchannel
,myrpt
->patchcontext
,myrpt
->exten
,1,NULL
))
8606 /* call has failed, inform user */
8607 myrpt
->callmode
= 4;
8609 rpt_mutex_unlock(&myrpt
->lock
);
8612 if ((myrpt
->callmode
== 2) || (myrpt
->callmode
== 3))
8616 rpt_mutex_unlock(&myrpt
->lock
);
8617 if ((myrpt
->dtmfidx
< 0) && myrpt
->p
.propagate_phonedtmf
)
8618 do_dtmf_phone(myrpt
,NULL
,c
);
8623 /* place an ID event in the telemetry queue */
8625 static void queue_id(struct rpt
*myrpt
)
8627 if(myrpt
->p
.idtime
){ /* ID time must be non-zero */
8628 myrpt
->mustid
= myrpt
->tailid
= 0;
8629 myrpt
->idtimer
= myrpt
->p
.idtime
; /* Reset our ID timer */
8630 rpt_mutex_unlock(&myrpt
->lock
);
8631 rpt_telemetry(myrpt
,ID
,NULL
);
8632 rpt_mutex_lock(&myrpt
->lock
);
8637 /* must be called locked */
8639 static void do_scheduler(struct rpt
*myrpt
)
8643 struct ast_variable
*skedlist
;
8644 char *strs
[5],*vp
,*val
,value
[100];
8646 memcpy(&myrpt
->lasttv
, &myrpt
->curtv
, sizeof(struct timeval
));
8648 if( (res
= gettimeofday(&myrpt
->curtv
, NULL
)) < 0)
8649 ast_log(LOG_NOTICE
, "Scheduler gettime of day returned: %s\n", strerror(res
));
8651 /* Try to get close to a 1 second resolution */
8653 if(myrpt
->lasttv
.tv_sec
== myrpt
->curtv
.tv_sec
)
8656 rpt_localtime(&myrpt
->curtv
.tv_sec
, &tmnow
);
8658 /* If midnight, then reset all daily statistics */
8660 if((tmnow
.tm_hour
== 0)&&(tmnow
.tm_min
== 0)&&(tmnow
.tm_sec
== 0)){
8661 myrpt
->dailykeyups
= 0;
8662 myrpt
->dailytxtime
= 0;
8663 myrpt
->dailykerchunks
= 0;
8664 myrpt
->dailyexecdcommands
= 0;
8667 if(tmnow
.tm_sec
!= 0)
8670 /* Code below only executes once per minute */
8673 /* Don't schedule if remote */
8678 /* Don't schedule if disabled */
8680 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].schedulerdisable
){
8682 ast_log(LOG_NOTICE
, "Scheduler disabled\n");
8686 if(!myrpt
->p
.skedstanzaname
){ /* No stanza means we do nothing */
8688 ast_log(LOG_NOTICE
,"No stanza for scheduler in rpt.conf\n");
8692 /* get pointer to linked list of scheduler entries */
8693 skedlist
= ast_variable_browse(myrpt
->cfg
, myrpt
->p
.skedstanzaname
);
8696 ast_log(LOG_NOTICE
, "Time now: %02d:%02d %02d %02d %02d\n",
8697 tmnow
.tm_hour
,tmnow
.tm_min
,tmnow
.tm_mday
,tmnow
.tm_mon
+ 1, tmnow
.tm_wday
);
8700 for(; skedlist
; skedlist
= skedlist
->next
){
8702 ast_log(LOG_NOTICE
, "Scheduler entry %s = %s being considered\n",skedlist
->name
, skedlist
->value
);
8703 strncpy(value
,skedlist
->value
,99);
8705 /* point to the substrings for minute, hour, dom, month, and dow */
8706 for( i
= 0, vp
= value
; i
< 5; i
++){
8709 while((*vp
== ' ') || (*vp
== 0x09)) /* get rid of any leading white space */
8711 strs
[i
] = vp
; /* save pointer to beginning of substring */
8712 while((*vp
!= ' ') && (*vp
!= 0x09) && (*vp
!= 0)) /* skip over substring */
8715 *vp
++ = 0; /* mark end of substring */
8718 ast_log(LOG_NOTICE
, "i = %d, min = %s, hour = %s, mday=%s, mon=%s, wday=%s\n",i
,
8719 strs
[0], strs
[1], strs
[2], strs
[3], strs
[4]);
8721 if((*strs
[0] != '*')&&(atoi(strs
[0]) != tmnow
.tm_min
))
8723 if((*strs
[1] != '*')&&(atoi(strs
[1]) != tmnow
.tm_hour
))
8725 if((*strs
[2] != '*')&&(atoi(strs
[2]) != tmnow
.tm_mday
))
8727 if((*strs
[3] != '*')&&(atoi(strs
[3]) != tmnow
.tm_mon
+ 1))
8729 if(atoi(strs
[4]) == 7)
8731 if((*strs
[4] != '*')&&(atoi(strs
[4]) != tmnow
.tm_wday
))
8734 ast_log(LOG_NOTICE
, "Executing scheduler entry %s = %s\n", skedlist
->name
, skedlist
->value
);
8735 if(atoi(skedlist
->name
) == 0)
8736 return; /* Zero is reserved for the startup macro */
8737 val
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->p
.macro
, skedlist
->name
);
8739 ast_log(LOG_WARNING
,"Scheduler could not find macro %s\n",skedlist
->name
);
8740 return; /* Macro not found */
8742 if ((MAXMACRO
- strlen(myrpt
->macrobuf
)) < strlen(val
)){
8743 ast_log(LOG_WARNING
, "Scheduler could not execute macro %s: Macro buffer full\n",
8745 return; /* Macro buffer full */
8747 myrpt
->macrotimer
= MACROTIME
;
8748 strncat(myrpt
->macrobuf
,val
,MAXMACRO
- strlen(myrpt
->macrobuf
) - 1);
8751 ast_log(LOG_WARNING
,"Malformed scheduler entry in rpt.conf: %s = %s\n",
8752 skedlist
->name
, skedlist
->value
);
8758 /* single thread with one file (request) to dial */
8759 static void *rpt(void *this)
8761 struct rpt
*myrpt
= (struct rpt
*)this;
8762 char *tele
,*idtalkover
,c
;
8763 int ms
= MSWAIT
,i
,lasttx
=0,val
,remrx
=0,identqueued
,othertelemqueued
;
8764 int tailmessagequeued
,ctqueued
,dtmfed
;
8765 struct ast_channel
*who
;
8766 ZT_CONFINFO ci
; /* conference info */
8768 struct rpt_link
*l
,*m
;
8769 struct rpt_tele
*telem
;
8770 char tmpstr
[300],lstr
[MAXLINKLIST
];
8773 if (myrpt
->p
.archivedir
) mkdir(myrpt
->p
.archivedir
,0600);
8774 sprintf(tmpstr
,"%s/%s",myrpt
->p
.archivedir
,myrpt
->name
);
8776 rpt_mutex_lock(&myrpt
->lock
);
8778 telem
= myrpt
->tele
.next
;
8779 while(telem
!= &myrpt
->tele
)
8781 ast_softhangup(telem
->chan
,AST_SOFTHANGUP_DEV
);
8782 telem
= telem
->next
;
8784 rpt_mutex_unlock(&myrpt
->lock
);
8785 /* find our index, and load the vars initially */
8786 for(i
= 0; i
< nrpts
; i
++)
8788 if (&rpt_vars
[i
] == myrpt
)
8794 rpt_mutex_lock(&myrpt
->lock
);
8795 strncpy(tmpstr
,myrpt
->rxchanname
,sizeof(tmpstr
) - 1);
8796 tele
= strchr(tmpstr
,'/');
8799 fprintf(stderr
,"rpt:Rxchannel Dial number (%s) must be in format tech/number\n",myrpt
->rxchanname
);
8800 rpt_mutex_unlock(&myrpt
->lock
);
8801 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8805 myrpt
->rxchannel
= ast_request(tmpstr
,AST_FORMAT_SLINEAR
,tele
,NULL
);
8806 myrpt
->zaprxchannel
= NULL
;
8807 if (!strcasecmp(tmpstr
,"Zap"))
8808 myrpt
->zaprxchannel
= myrpt
->rxchannel
;
8809 if (myrpt
->rxchannel
)
8811 if (myrpt
->rxchannel
->_state
== AST_STATE_BUSY
)
8813 fprintf(stderr
,"rpt:Sorry unable to obtain Rx channel\n");
8814 rpt_mutex_unlock(&myrpt
->lock
);
8815 ast_hangup(myrpt
->rxchannel
);
8816 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8819 ast_set_read_format(myrpt
->rxchannel
,AST_FORMAT_SLINEAR
);
8820 ast_set_write_format(myrpt
->rxchannel
,AST_FORMAT_SLINEAR
);
8821 #ifdef AST_CDR_FLAG_POST_DISABLED
8822 ast_set_flag(myrpt
->rxchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
8824 myrpt
->rxchannel
->whentohangup
= 0;
8825 myrpt
->rxchannel
->appl
= "Apprpt";
8826 myrpt
->rxchannel
->data
= "(Repeater Rx)";
8827 if (option_verbose
> 2)
8828 ast_verbose(VERBOSE_PREFIX_3
"rpt (Rx) initiating call to %s/%s on %s\n",
8829 tmpstr
,tele
,myrpt
->rxchannel
->name
);
8830 ast_call(myrpt
->rxchannel
,tele
,999);
8831 if (myrpt
->rxchannel
->_state
!= AST_STATE_UP
)
8833 rpt_mutex_unlock(&myrpt
->lock
);
8834 ast_hangup(myrpt
->rxchannel
);
8835 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8841 fprintf(stderr
,"rpt:Sorry unable to obtain Rx channel\n");
8842 rpt_mutex_unlock(&myrpt
->lock
);
8843 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8846 myrpt
->zaptxchannel
= NULL
;
8847 if (myrpt
->txchanname
)
8849 strncpy(tmpstr
,myrpt
->txchanname
,sizeof(tmpstr
) - 1);
8850 tele
= strchr(tmpstr
,'/');
8853 fprintf(stderr
,"rpt:Txchannel Dial number (%s) must be in format tech/number\n",myrpt
->txchanname
);
8854 rpt_mutex_unlock(&myrpt
->lock
);
8855 ast_hangup(myrpt
->rxchannel
);
8856 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8860 myrpt
->txchannel
= ast_request(tmpstr
,AST_FORMAT_SLINEAR
,tele
,NULL
);
8861 if (!strcasecmp(tmpstr
,"Zap"))
8862 myrpt
->zaptxchannel
= myrpt
->txchannel
;
8863 if (myrpt
->txchannel
)
8865 if (myrpt
->txchannel
->_state
== AST_STATE_BUSY
)
8867 fprintf(stderr
,"rpt:Sorry unable to obtain Tx channel\n");
8868 rpt_mutex_unlock(&myrpt
->lock
);
8869 ast_hangup(myrpt
->txchannel
);
8870 ast_hangup(myrpt
->rxchannel
);
8871 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8874 ast_set_read_format(myrpt
->txchannel
,AST_FORMAT_SLINEAR
);
8875 ast_set_write_format(myrpt
->txchannel
,AST_FORMAT_SLINEAR
);
8876 #ifdef AST_CDR_FLAG_POST_DISABLED
8877 ast_set_flag(myrpt
->txchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
8879 myrpt
->txchannel
->whentohangup
= 0;
8880 myrpt
->txchannel
->appl
= "Apprpt";
8881 myrpt
->txchannel
->data
= "(Repeater Tx)";
8882 if (option_verbose
> 2)
8883 ast_verbose(VERBOSE_PREFIX_3
"rpt (Tx) initiating call to %s/%s on %s\n",
8884 tmpstr
,tele
,myrpt
->txchannel
->name
);
8885 ast_call(myrpt
->txchannel
,tele
,999);
8886 if (myrpt
->rxchannel
->_state
!= AST_STATE_UP
)
8888 rpt_mutex_unlock(&myrpt
->lock
);
8889 ast_hangup(myrpt
->rxchannel
);
8890 ast_hangup(myrpt
->txchannel
);
8891 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8897 fprintf(stderr
,"rpt:Sorry unable to obtain Tx channel\n");
8898 rpt_mutex_unlock(&myrpt
->lock
);
8899 ast_hangup(myrpt
->rxchannel
);
8900 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8906 myrpt
->txchannel
= myrpt
->rxchannel
;
8908 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_KEY
);
8909 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_UNKEY
);
8910 /* allocate a pseudo-channel thru asterisk */
8911 myrpt
->pchannel
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
8912 if (!myrpt
->pchannel
)
8914 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
8915 rpt_mutex_unlock(&myrpt
->lock
);
8916 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
8917 ast_hangup(myrpt
->txchannel
);
8918 ast_hangup(myrpt
->rxchannel
);
8919 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8922 #ifdef AST_CDR_FLAG_POST_DISABLED
8923 ast_set_flag(myrpt
->pchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
8925 if (!myrpt
->zaprxchannel
) myrpt
->zaprxchannel
= myrpt
->pchannel
;
8926 if (!myrpt
->zaptxchannel
)
8928 /* allocate a pseudo-channel thru asterisk */
8929 myrpt
->zaptxchannel
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
8930 if (!myrpt
->zaptxchannel
)
8932 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
8933 rpt_mutex_unlock(&myrpt
->lock
);
8934 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
8935 ast_hangup(myrpt
->txchannel
);
8936 ast_hangup(myrpt
->rxchannel
);
8937 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8940 ast_set_read_format(myrpt
->zaptxchannel
,AST_FORMAT_SLINEAR
);
8941 ast_set_write_format(myrpt
->zaptxchannel
,AST_FORMAT_SLINEAR
);
8942 #ifdef AST_CDR_FLAG_POST_DISABLED
8943 ast_set_flag(myrpt
->zaptxchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
8946 /* allocate a pseudo-channel thru asterisk */
8947 myrpt
->monchannel
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
8948 if (!myrpt
->monchannel
)
8950 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
8951 rpt_mutex_unlock(&myrpt
->lock
);
8952 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
8953 ast_hangup(myrpt
->txchannel
);
8954 ast_hangup(myrpt
->rxchannel
);
8955 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8958 ast_set_read_format(myrpt
->monchannel
,AST_FORMAT_SLINEAR
);
8959 ast_set_write_format(myrpt
->monchannel
,AST_FORMAT_SLINEAR
);
8960 #ifdef AST_CDR_FLAG_POST_DISABLED
8961 ast_set_flag(myrpt
->monchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
8963 /* make a conference for the tx */
8965 ci
.confno
= -1; /* make a new conf */
8966 ci
.confmode
= ZT_CONF_CONF
| ZT_CONF_LISTENER
;
8967 /* first put the channel on the conference in proper mode */
8968 if (ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_SETCONF
,&ci
) == -1)
8970 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
8971 rpt_mutex_unlock(&myrpt
->lock
);
8972 ast_hangup(myrpt
->pchannel
);
8973 ast_hangup(myrpt
->monchannel
);
8974 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
8975 ast_hangup(myrpt
->txchannel
);
8976 ast_hangup(myrpt
->rxchannel
);
8977 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8980 /* save tx conference number */
8981 myrpt
->txconf
= ci
.confno
;
8982 /* make a conference for the pseudo */
8984 ci
.confno
= -1; /* make a new conf */
8985 ci
.confmode
= ((myrpt
->p
.duplex
== 2) || (myrpt
->p
.duplex
== 4)) ? ZT_CONF_CONFANNMON
:
8986 (ZT_CONF_CONF
| ZT_CONF_LISTENER
| ZT_CONF_TALKER
);
8987 /* first put the channel on the conference in announce mode */
8988 if (ioctl(myrpt
->pchannel
->fds
[0],ZT_SETCONF
,&ci
) == -1)
8990 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
8991 rpt_mutex_unlock(&myrpt
->lock
);
8992 ast_hangup(myrpt
->pchannel
);
8993 ast_hangup(myrpt
->monchannel
);
8994 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
8995 ast_hangup(myrpt
->txchannel
);
8996 ast_hangup(myrpt
->rxchannel
);
8997 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
9000 /* save pseudo channel conference number */
9001 myrpt
->conf
= ci
.confno
;
9002 /* make a conference for the pseudo */
9004 if ((strstr(myrpt
->txchannel
->name
,"pseudo") == NULL
) &&
9005 (myrpt
->zaptxchannel
== myrpt
->txchannel
))
9007 /* get tx channel's port number */
9008 if (ioctl(myrpt
->txchannel
->fds
[0],ZT_CHANNO
,&ci
.confno
) == -1)
9010 ast_log(LOG_WARNING
, "Unable to set tx channel's chan number\n");
9011 rpt_mutex_unlock(&myrpt
->lock
);
9012 ast_hangup(myrpt
->pchannel
);
9013 ast_hangup(myrpt
->monchannel
);
9014 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
9015 ast_hangup(myrpt
->txchannel
);
9016 ast_hangup(myrpt
->rxchannel
);
9017 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
9020 ci
.confmode
= ZT_CONF_MONITORTX
;
9024 ci
.confno
= myrpt
->txconf
;
9025 ci
.confmode
= ZT_CONF_CONFANNMON
;
9027 /* first put the channel on the conference in announce mode */
9028 if (ioctl(myrpt
->monchannel
->fds
[0],ZT_SETCONF
,&ci
) == -1)
9030 ast_log(LOG_WARNING
, "Unable to set conference mode for monitor\n");
9031 rpt_mutex_unlock(&myrpt
->lock
);
9032 ast_hangup(myrpt
->pchannel
);
9033 ast_hangup(myrpt
->monchannel
);
9034 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
9035 ast_hangup(myrpt
->txchannel
);
9036 ast_hangup(myrpt
->rxchannel
);
9037 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
9040 /* allocate a pseudo-channel thru asterisk */
9041 myrpt
->txpchannel
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
9042 if (!myrpt
->txpchannel
)
9044 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
9045 rpt_mutex_unlock(&myrpt
->lock
);
9046 ast_hangup(myrpt
->pchannel
);
9047 ast_hangup(myrpt
->monchannel
);
9048 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
9049 ast_hangup(myrpt
->txchannel
);
9050 ast_hangup(myrpt
->rxchannel
);
9051 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
9054 #ifdef AST_CDR_FLAG_POST_DISABLED
9055 ast_set_flag(myrpt
->txpchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
9057 /* make a conference for the tx */
9059 ci
.confno
= myrpt
->txconf
;
9060 ci
.confmode
= ZT_CONF_CONF
| ZT_CONF_TALKER
;
9061 /* first put the channel on the conference in proper mode */
9062 if (ioctl(myrpt
->txpchannel
->fds
[0],ZT_SETCONF
,&ci
) == -1)
9064 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
9065 rpt_mutex_unlock(&myrpt
->lock
);
9066 ast_hangup(myrpt
->txpchannel
);
9067 ast_hangup(myrpt
->monchannel
);
9068 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
9069 ast_hangup(myrpt
->txchannel
);
9070 ast_hangup(myrpt
->rxchannel
);
9071 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
9074 /* Now, the idea here is to copy from the physical rx channel buffer
9075 into the pseudo tx buffer, and from the pseudo rx buffer into the
9076 tx channel buffer */
9077 myrpt
->links
.next
= &myrpt
->links
;
9078 myrpt
->links
.prev
= &myrpt
->links
;
9079 myrpt
->tailtimer
= 0;
9081 myrpt
->tmsgtimer
= myrpt
->p
.tailmessagetime
;
9082 myrpt
->idtimer
= myrpt
->p
.politeid
;
9083 myrpt
->mustid
= myrpt
->tailid
= 0;
9084 myrpt
->callmode
= 0;
9085 myrpt
->tounkeyed
= 0;
9086 myrpt
->tonotify
= 0;
9087 myrpt
->retxtimer
= 0;
9088 myrpt
->rerxtimer
= 0;
9089 myrpt
->skedtimer
= 0;
9090 myrpt
->tailevent
= 0;
9093 idtalkover
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->name
, "idtalkover");
9094 myrpt
->dtmfidx
= -1;
9095 myrpt
->dtmfbuf
[0] = 0;
9096 myrpt
->rem_dtmfidx
= -1;
9097 myrpt
->rem_dtmfbuf
[0] = 0;
9098 myrpt
->dtmf_time
= 0;
9099 myrpt
->rem_dtmf_time
= 0;
9100 myrpt
->disgorgetime
= 0;
9101 myrpt
->lastnodewhichkeyedusup
[0] = '\0';
9102 myrpt
->dailytxtime
= 0;
9103 myrpt
->totaltxtime
= 0;
9104 myrpt
->dailykeyups
= 0;
9105 myrpt
->totalkeyups
= 0;
9106 myrpt
->dailykerchunks
= 0;
9107 myrpt
->totalkerchunks
= 0;
9108 myrpt
->dailyexecdcommands
= 0;
9109 myrpt
->totalexecdcommands
= 0;
9110 myrpt
->timeouts
= 0;
9111 myrpt
->exten
[0] = '\0';
9112 myrpt
->lastdtmfcommand
[0] = '\0';
9113 if (myrpt
->p
.startupmacro
)
9115 snprintf(myrpt
->macrobuf
,MAXMACRO
- 1,"PPPP%s",myrpt
->p
.startupmacro
);
9117 rpt_mutex_unlock(&myrpt
->lock
);
9119 ast_channel_setoption(myrpt
->rxchannel
,AST_OPTION_RELAXDTMF
,&val
,sizeof(char),0);
9121 ast_channel_setoption(myrpt
->rxchannel
,AST_OPTION_TONE_VERIFY
,&val
,sizeof(char),0);
9122 if (myrpt
->p
.archivedir
) donodelog(myrpt
,"STARTUP");
9126 struct ast_frame
*f
,*f1
,*f2
;
9127 struct ast_channel
*cs
[300],*cs1
[300];
9128 int totx
=0,elap
=0,n
,x
,toexit
=0;
9131 if((myrpt
->disgorgetime
) && (time(NULL
) >= myrpt
->disgorgetime
)){
9132 struct rpt_link
*zl
;
9133 struct rpt_tele
*zt
;
9135 myrpt
->disgorgetime
= 0;
9136 ast_log(LOG_NOTICE
,"********** Variable Dump Start (app_rpt) **********\n");
9137 ast_log(LOG_NOTICE
,"totx = %d\n",totx
);
9138 ast_log(LOG_NOTICE
,"remrx = %d\n",remrx
);
9139 ast_log(LOG_NOTICE
,"lasttx = %d\n",lasttx
);
9140 ast_log(LOG_NOTICE
,"elap = %d\n",elap
);
9141 ast_log(LOG_NOTICE
,"toexit = %d\n",toexit
);
9143 ast_log(LOG_NOTICE
,"myrpt->keyed = %d\n",myrpt
->keyed
);
9144 ast_log(LOG_NOTICE
,"myrpt->localtx = %d\n",myrpt
->localtx
);
9145 ast_log(LOG_NOTICE
,"myrpt->callmode = %d\n",myrpt
->callmode
);
9146 ast_log(LOG_NOTICE
,"myrpt->mustid = %d\n",myrpt
->mustid
);
9147 ast_log(LOG_NOTICE
,"myrpt->tounkeyed = %d\n",myrpt
->tounkeyed
);
9148 ast_log(LOG_NOTICE
,"myrpt->tonotify = %d\n",myrpt
->tonotify
);
9149 ast_log(LOG_NOTICE
,"myrpt->retxtimer = %ld\n",myrpt
->retxtimer
);
9150 ast_log(LOG_NOTICE
,"myrpt->totimer = %d\n",myrpt
->totimer
);
9151 ast_log(LOG_NOTICE
,"myrpt->tailtimer = %d\n",myrpt
->tailtimer
);
9152 ast_log(LOG_NOTICE
,"myrpt->tailevent = %d\n",myrpt
->tailevent
);
9154 zl
= myrpt
->links
.next
;
9155 while(zl
!= &myrpt
->links
){
9156 ast_log(LOG_NOTICE
,"*** Link Name: %s ***\n",zl
->name
);
9157 ast_log(LOG_NOTICE
," link->lasttx %d\n",zl
->lasttx
);
9158 ast_log(LOG_NOTICE
," link->lastrx %d\n",zl
->lastrx
);
9159 ast_log(LOG_NOTICE
," link->connected %d\n",zl
->connected
);
9160 ast_log(LOG_NOTICE
," link->hasconnected %d\n",zl
->hasconnected
);
9161 ast_log(LOG_NOTICE
," link->outbound %d\n",zl
->outbound
);
9162 ast_log(LOG_NOTICE
," link->disced %d\n",zl
->disced
);
9163 ast_log(LOG_NOTICE
," link->killme %d\n",zl
->killme
);
9164 ast_log(LOG_NOTICE
," link->disctime %ld\n",zl
->disctime
);
9165 ast_log(LOG_NOTICE
," link->retrytimer %ld\n",zl
->retrytimer
);
9166 ast_log(LOG_NOTICE
," link->retries = %d\n",zl
->retries
);
9167 ast_log(LOG_NOTICE
," link->reconnects = %d\n",zl
->reconnects
);
9171 zt
= myrpt
->tele
.next
;
9172 if(zt
!= &myrpt
->tele
)
9173 ast_log(LOG_NOTICE
,"*** Telemetry Queue ***\n");
9174 while(zt
!= &myrpt
->tele
){
9175 ast_log(LOG_NOTICE
," Telemetry mode: %d\n",zt
->mode
);
9178 ast_log(LOG_NOTICE
,"******* Variable Dump End (app_rpt) *******\n");
9185 struct rpt_tele
*telem
;
9187 rpt_mutex_lock(&myrpt
->lock
);
9188 telem
= myrpt
->tele
.next
;
9189 while(telem
!= &myrpt
->tele
)
9191 ast_softhangup(telem
->chan
,AST_SOFTHANGUP_DEV
);
9192 telem
= telem
->next
;
9195 rpt_mutex_unlock(&myrpt
->lock
);
9197 /* find our index, and load the vars */
9198 for(i
= 0; i
< nrpts
; i
++)
9200 if (&rpt_vars
[i
] == myrpt
)
9208 rpt_mutex_lock(&myrpt
->lock
);
9209 if (ast_check_hangup(myrpt
->rxchannel
)) break;
9210 if (ast_check_hangup(myrpt
->txchannel
)) break;
9211 if (ast_check_hangup(myrpt
->pchannel
)) break;
9212 if (ast_check_hangup(myrpt
->monchannel
)) break;
9213 if (ast_check_hangup(myrpt
->txpchannel
)) break;
9214 if (myrpt
->zaptxchannel
&& ast_check_hangup(myrpt
->zaptxchannel
)) break;
9216 /* Set local tx with keyed */
9217 myrpt
->localtx
= myrpt
->keyed
;
9218 /* If someone's connected, and they're transmitting from their end to us, set remrx true */
9219 l
= myrpt
->links
.next
;
9221 while(l
!= &myrpt
->links
)
9225 if(l
->name
[0] != '0') /* Ignore '0' nodes */
9226 strcpy(myrpt
->lastnodewhichkeyedusup
, l
->name
); /* Note the node which is doing the key up */
9230 /* Create a "must_id" flag for the cleanup ID */
9231 if(myrpt
->p
.idtime
) /* ID time must be non-zero */
9232 myrpt
->mustid
|= (myrpt
->idtimer
) && (myrpt
->keyed
|| remrx
) ;
9233 /* Build a fresh totx from myrpt->keyed and autopatch activated */
9234 totx
= myrpt
->callmode
;
9235 /* If full duplex, add local tx to totx */
9236 if (myrpt
->p
.duplex
> 1)
9238 totx
= totx
|| myrpt
->localtx
;
9240 /* Traverse the telemetry list to see what's queued */
9242 othertelemqueued
= 0;
9243 tailmessagequeued
= 0;
9245 telem
= myrpt
->tele
.next
;
9246 while(telem
!= &myrpt
->tele
)
9248 if((telem
->mode
== ID
) || (telem
->mode
== IDTALKOVER
)){
9249 identqueued
= 1; /* Identification telemetry */
9251 else if(telem
->mode
== TAILMSG
)
9253 tailmessagequeued
= 1; /* Tail message telemetry */
9257 if ((telem
->mode
!= UNKEY
) && (telem
->mode
!= LINKUNKEY
))
9258 othertelemqueued
= 1; /* Other telemetry */
9260 ctqueued
= 1; /* Courtesy tone telemetry */
9262 telem
= telem
->next
;
9265 /* Add in any "other" telemetry, unless specified otherwise */
9266 if (!myrpt
->p
.notelemtx
) totx
= totx
|| othertelemqueued
;
9267 /* Update external (to links) transmitter PTT state with everything but ID, CT, and tailmessage telemetry */
9268 myrpt
->exttx
= totx
;
9269 totx
= totx
|| myrpt
->dtmf_local_timer
;
9270 /* If half or 3/4 duplex, add localtx to external link tx */
9271 if (myrpt
->p
.duplex
< 2) myrpt
->exttx
= myrpt
->exttx
|| myrpt
->localtx
;
9272 /* Add in ID telemetry to local transmitter */
9273 totx
= totx
|| remrx
;
9274 /* If 3/4 or full duplex, add in ident and CT telemetry */
9275 if (myrpt
->p
.duplex
> 0)
9276 totx
= totx
|| identqueued
|| ctqueued
;
9277 /* If full duplex, add local dtmf stuff active */
9278 if (myrpt
->p
.duplex
> 1)
9280 totx
= totx
|| (myrpt
->dtmfidx
> -1) ||
9283 /* Reset time out timer variables if there is no activity */
9286 myrpt
->totimer
= myrpt
->p
.totime
;
9287 myrpt
->tounkeyed
= 0;
9288 myrpt
->tonotify
= 0;
9291 myrpt
->tailtimer
= myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].alternatetail
?
9292 myrpt
->p
.althangtime
: /* Initialize tail timer */
9295 /* Disable the local transmitter if we are timed out */
9296 totx
= totx
&& myrpt
->totimer
;
9297 /* if timed-out and not said already, say it */
9298 if ((!myrpt
->totimer
) && (!myrpt
->tonotify
))
9300 myrpt
->tonotify
= 1;
9302 rpt_mutex_unlock(&myrpt
->lock
);
9303 rpt_telemetry(myrpt
,TIMEOUT
,NULL
);
9304 rpt_mutex_lock(&myrpt
->lock
);
9307 /* If unkey and re-key, reset time out timer */
9308 if ((!totx
) && (!myrpt
->totimer
) && (!myrpt
->tounkeyed
) && (!myrpt
->keyed
))
9310 myrpt
->tounkeyed
= 1;
9312 if ((!totx
) && (!myrpt
->totimer
) && myrpt
->tounkeyed
&& myrpt
->keyed
)
9314 myrpt
->totimer
= myrpt
->p
.totime
;
9315 myrpt
->tounkeyed
= 0;
9316 myrpt
->tonotify
= 0;
9317 rpt_mutex_unlock(&myrpt
->lock
);
9320 /* if timed-out and in circuit busy after call */
9321 if ((!totx
) && (!myrpt
->totimer
) && (myrpt
->callmode
== 4))
9323 myrpt
->callmode
= 0;
9325 /* get rid of tail if timed out */
9326 if (!myrpt
->totimer
) myrpt
->tailtimer
= 0;
9327 /* if not timed-out, add in tail */
9328 if (myrpt
->totimer
) totx
= totx
|| myrpt
->tailtimer
;
9329 /* If user or links key up or are keyed up over standard ID, switch to talkover ID, if one is defined */
9330 /* If tail message, kill the message if someone keys up over it */
9331 if ((myrpt
->keyed
|| remrx
) && ((identqueued
&& idtalkover
) || (tailmessagequeued
))) {
9332 int hasid
= 0,hastalkover
= 0;
9334 telem
= myrpt
->tele
.next
;
9335 while(telem
!= &myrpt
->tele
){
9336 if(telem
->mode
== ID
){
9337 if (telem
->chan
) ast_softhangup(telem
->chan
, AST_SOFTHANGUP_DEV
); /* Whoosh! */
9340 if(telem
->mode
== TAILMSG
){
9341 if (telem
->chan
) ast_softhangup(telem
->chan
, AST_SOFTHANGUP_DEV
); /* Whoosh! */
9343 if (telem
->mode
== IDTALKOVER
) hastalkover
= 1;
9344 telem
= telem
->next
;
9346 rpt_mutex_unlock(&myrpt
->lock
);
9347 if (hasid
&& (!hastalkover
)) rpt_telemetry(myrpt
, IDTALKOVER
, NULL
); /* Start Talkover ID */
9348 rpt_mutex_lock(&myrpt
->lock
);
9350 /* Try to be polite */
9351 /* If the repeater has been inactive for longer than the ID time, do an initial ID in the tail*/
9352 /* If within 30 seconds of the time to ID, try do it in the tail */
9353 /* else if at ID time limit, do it right over the top of them */
9354 /* Lastly, if the repeater has been keyed, and the ID timer is expired, do a clean up ID */
9355 if(myrpt
->mustid
&& (!myrpt
->idtimer
))
9358 if ((myrpt
->p
.idtime
&& totx
&& (!myrpt
->exttx
) &&
9359 (myrpt
->idtimer
<= myrpt
->p
.politeid
) && myrpt
->tailtimer
)) /* ID time must be non-zero */
9364 /* If tail timer expires, then check for tail messages */
9366 if(myrpt
->tailevent
){
9367 myrpt
->tailevent
= 0;
9372 else if ((myrpt
->p
.tailmessages
[0]) &&
9373 (myrpt
->p
.tailmessagetime
) && (myrpt
->tmsgtimer
== 0)){
9375 myrpt
->tmsgtimer
= myrpt
->p
.tailmessagetime
;
9376 rpt_mutex_unlock(&myrpt
->lock
);
9377 rpt_telemetry(myrpt
, TAILMSG
, NULL
);
9378 rpt_mutex_lock(&myrpt
->lock
);
9382 /* Main TX control */
9384 /* let telemetry transmit anyway (regardless of timeout) */
9385 if (myrpt
->p
.duplex
> 0) totx
= totx
|| (myrpt
->tele
.next
!= &myrpt
->tele
);
9386 if (totx
&& (!lasttx
))
9388 char mydate
[100],myfname
[100];
9391 if (myrpt
->monstream
) ast_closestream(myrpt
->monstream
);
9392 if (myrpt
->p
.archivedir
)
9397 strftime(mydate
,sizeof(mydate
) - 1,"%Y%m%d%H%M%S",
9399 sprintf(myfname
,"%s/%s/%s",myrpt
->p
.archivedir
,
9400 myrpt
->name
,mydate
);
9401 myrpt
->monstream
= ast_writefile(myfname
,"wav49",
9402 "app_rpt Air Archive",O_CREAT
| O_APPEND
,0,0600);
9403 if (myrpt
->p
.monminblocks
)
9405 blocksleft
= diskavail(myrpt
);
9406 if (blocksleft
>= myrpt
->p
.monminblocks
)
9407 donodelog(myrpt
,"TXKEY,MAIN");
9408 } else donodelog(myrpt
,"TXKEY,MAIN");
9411 myrpt
->dailykeyups
++;
9412 myrpt
->totalkeyups
++;
9413 rpt_mutex_unlock(&myrpt
->lock
);
9414 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_KEY
);
9415 rpt_mutex_lock(&myrpt
->lock
);
9417 totx
= totx
&& !myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
;
9418 if ((!totx
) && lasttx
)
9420 if (myrpt
->monstream
) ast_closestream(myrpt
->monstream
);
9421 myrpt
->monstream
= NULL
;
9424 rpt_mutex_unlock(&myrpt
->lock
);
9425 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_UNKEY
);
9426 rpt_mutex_lock(&myrpt
->lock
);
9427 donodelog(myrpt
,"TXUNKEY,MAIN");
9430 /* if DTMF timeout */
9431 if ((!myrpt
->cmdnode
[0]) && (myrpt
->dtmfidx
>= 0) && ((myrpt
->dtmf_time
+ DTMF_TIMEOUT
) < t
))
9433 myrpt
->dtmfidx
= -1;
9434 myrpt
->dtmfbuf
[0] = 0;
9436 /* if remote DTMF timeout */
9437 if ((myrpt
->rem_dtmfidx
>= 0) && ((myrpt
->rem_dtmf_time
+ DTMF_TIMEOUT
) < t
))
9439 myrpt
->rem_dtmfidx
= -1;
9440 myrpt
->rem_dtmfbuf
[0] = 0;
9445 l
= myrpt
->links
.next
;
9446 while(l
!= &myrpt
->links
)
9450 /* remove from queue */
9451 remque((struct qelem
*) l
);
9452 if (!strcmp(myrpt
->cmdnode
,l
->name
))
9453 myrpt
->cmdnode
[0] = 0;
9454 rpt_mutex_unlock(&myrpt
->lock
);
9455 /* hang-up on call to device */
9456 if (l
->chan
) ast_hangup(l
->chan
);
9457 ast_hangup(l
->pchan
);
9459 rpt_mutex_lock(&myrpt
->lock
);
9460 /* re-start link traversal */
9461 l
= myrpt
->links
.next
;
9467 cs
[n
++] = myrpt
->rxchannel
;
9468 cs
[n
++] = myrpt
->pchannel
;
9469 cs
[n
++] = myrpt
->monchannel
;
9470 cs
[n
++] = myrpt
->txpchannel
;
9471 if (myrpt
->txchannel
!= myrpt
->rxchannel
) cs
[n
++] = myrpt
->txchannel
;
9472 if (myrpt
->zaptxchannel
!= myrpt
->txchannel
)
9473 cs
[n
++] = myrpt
->zaptxchannel
;
9474 l
= myrpt
->links
.next
;
9475 while(l
!= &myrpt
->links
)
9477 if ((!l
->killme
) && (!l
->disctime
) && l
->chan
)
9484 rpt_mutex_unlock(&myrpt
->lock
);
9486 for(x
= 0; x
< n
; x
++)
9488 int s
= -(-x
- myrpt
->scram
- 1) % n
;
9492 who
= ast_waitfor_n(cs1
,n
,&ms
);
9493 if (who
== NULL
) ms
= 0;
9495 rpt_mutex_lock(&myrpt
->lock
);
9496 l
= myrpt
->links
.next
;
9497 while(l
!= &myrpt
->links
)
9499 if (l
->linklisttimer
)
9501 l
->linklisttimer
-= elap
;
9502 if (l
->linklisttimer
< 0) l
->linklisttimer
= 0;
9504 if ((!l
->linklisttimer
) && (l
->name
[0] != '0') && (!l
->isremote
))
9506 struct ast_frame lf
;
9508 memset(&lf
,0,sizeof(lf
));
9509 lf
.frametype
= AST_FRAME_TEXT
;
9514 l
->linklisttimer
= LINKLISTTIME
;
9516 __mklinklist(myrpt
,l
,lstr
+ 2);
9519 lf
.datalen
= strlen(lstr
) + 1;
9521 ast_write(l
->chan
,&lf
);
9522 if (debug
> 6) ast_log(LOG_NOTICE
,
9523 "@@@@ node %s sent node string %s to node %s\n",
9524 myrpt
->name
,lstr
,l
->name
);
9528 if ((l
->retxtimer
+= elap
) >= REDUNDANT_TX_TIME
)
9531 if (l
->chan
&& l
->phonemode
== 0)
9534 ast_indicate(l
->chan
,AST_CONTROL_RADIO_KEY
);
9536 ast_indicate(l
->chan
,AST_CONTROL_RADIO_UNKEY
);
9539 if ((l
->rerxtimer
+= elap
) >= (REDUNDANT_TX_TIME
* 5))
9541 if (debug
== 7) printf("@@@@ rx un-key\n");
9545 rpt_telemetry(myrpt
,LINKUNKEY
,l
);
9546 if (myrpt
->p
.archivedir
)
9551 sprintf(str
,"RXUNKEY(T),%s",l
->name
);
9552 donodelog(myrpt
,str
);
9556 if (l
->disctime
) /* Disconnect timer active on a channel ? */
9558 l
->disctime
-= elap
;
9559 if (l
->disctime
<= 0) /* Disconnect timer expired on inbound channel ? */
9560 l
->disctime
= 0; /* Yep */
9565 l
->retrytimer
-= elap
;
9566 if (l
->retrytimer
< 0) l
->retrytimer
= 0;
9569 /* Tally connect time */
9570 l
->connecttime
+= elap
;
9572 /* ignore non-timing channels */
9573 if (l
->elaptime
< 0)
9578 l
->elaptime
+= elap
;
9579 /* if connection has taken too long */
9580 if ((l
->elaptime
> MAXCONNECTTIME
) &&
9581 ((!l
->chan
) || (l
->chan
->_state
!= AST_STATE_UP
)))
9584 rpt_mutex_unlock(&myrpt
->lock
);
9585 if (l
->chan
) ast_softhangup(l
->chan
,AST_SOFTHANGUP_DEV
);
9586 rpt_mutex_lock(&myrpt
->lock
);
9589 if ((!l
->chan
) && (!l
->retrytimer
) && l
->outbound
&&
9590 (l
->retries
++ < l
->max_retries
) && (l
->hasconnected
))
9592 if (l
->chan
) ast_hangup(l
->chan
);
9594 rpt_mutex_unlock(&myrpt
->lock
);
9595 if ((l
->name
[0] != '0') && (!l
->isremote
))
9597 if (attempt_reconnect(myrpt
,l
) == -1)
9599 l
->retrytimer
= RETRY_TIMER_MS
;
9604 l
->retrytimer
= l
->max_retries
+ 1;
9607 rpt_mutex_lock(&myrpt
->lock
);
9610 if ((!l
->chan
) && (!l
->retrytimer
) && l
->outbound
&&
9611 (l
->retries
>= l
->max_retries
))
9613 /* remove from queue */
9614 remque((struct qelem
*) l
);
9615 if (!strcmp(myrpt
->cmdnode
,l
->name
))
9616 myrpt
->cmdnode
[0] = 0;
9617 rpt_mutex_unlock(&myrpt
->lock
);
9618 if (l
->name
[0] != '0')
9620 if (!l
->hasconnected
)
9621 rpt_telemetry(myrpt
,CONNFAIL
,l
);
9622 else rpt_telemetry(myrpt
,REMDISC
,l
);
9624 if (myrpt
->p
.archivedir
)
9628 if (!l
->hasconnected
)
9629 sprintf(str
,"LINKFAIL,%s",l
->name
);
9631 sprintf(str
,"LINKDISC,%s",l
->name
);
9632 donodelog(myrpt
,str
);
9634 /* hang-up on call to device */
9635 ast_hangup(l
->pchan
);
9637 rpt_mutex_lock(&myrpt
->lock
);
9640 if ((!l
->chan
) && (!l
->disctime
) && (!l
->outbound
))
9642 /* remove from queue */
9643 remque((struct qelem
*) l
);
9644 if (!strcmp(myrpt
->cmdnode
,l
->name
))
9645 myrpt
->cmdnode
[0] = 0;
9646 rpt_mutex_unlock(&myrpt
->lock
);
9647 if (l
->name
[0] != '0')
9649 rpt_telemetry(myrpt
,REMDISC
,l
);
9651 if (myrpt
->p
.archivedir
)
9655 sprintf(str
,"LINKDISC,%s",l
->name
);
9656 donodelog(myrpt
,str
);
9658 /* hang-up on call to device */
9659 ast_hangup(l
->pchan
);
9661 rpt_mutex_lock(&myrpt
->lock
);
9667 myrpt
->dailytxtime
+= elap
;
9668 myrpt
->totaltxtime
+= elap
;
9670 i
= myrpt
->tailtimer
;
9671 if (myrpt
->tailtimer
) myrpt
->tailtimer
-= elap
;
9672 if (myrpt
->tailtimer
< 0) myrpt
->tailtimer
= 0;
9673 if((i
) && (myrpt
->tailtimer
== 0))
9674 myrpt
->tailevent
= 1;
9675 if ((!myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].totdisable
) && myrpt
->totimer
) myrpt
->totimer
-= elap
;
9676 if (myrpt
->totimer
< 0) myrpt
->totimer
= 0;
9677 if (myrpt
->idtimer
) myrpt
->idtimer
-= elap
;
9678 if (myrpt
->idtimer
< 0) myrpt
->idtimer
= 0;
9679 if (myrpt
->tmsgtimer
) myrpt
->tmsgtimer
-= elap
;
9680 if (myrpt
->tmsgtimer
< 0) myrpt
->tmsgtimer
= 0;
9681 /* do macro timers */
9682 if (myrpt
->macrotimer
) myrpt
->macrotimer
-= elap
;
9683 if (myrpt
->macrotimer
< 0) myrpt
->macrotimer
= 0;
9684 /* do local dtmf timer */
9685 if (myrpt
->dtmf_local_timer
)
9687 if (myrpt
->dtmf_local_timer
> 1) myrpt
->dtmf_local_timer
-= elap
;
9688 if (myrpt
->dtmf_local_timer
< 1) myrpt
->dtmf_local_timer
= 1;
9690 do_dtmf_local(myrpt
,0);
9691 /* Execute scheduler appx. every 2 tenths of a second */
9692 if (myrpt
->skedtimer
<= 0){
9693 myrpt
->skedtimer
= 200;
9694 do_scheduler(myrpt
);
9697 myrpt
->skedtimer
-=elap
;
9700 rpt_mutex_unlock(&myrpt
->lock
);
9703 c
= myrpt
->macrobuf
[0];
9705 if (c
&& (!myrpt
->macrotimer
) &&
9706 starttime
&& (t
> (starttime
+ START_DELAY
)))
9708 myrpt
->macrotimer
= MACROTIME
;
9709 memmove(myrpt
->macrobuf
,myrpt
->macrobuf
+ 1,MAXMACRO
- 1);
9710 if ((c
== 'p') || (c
== 'P'))
9711 myrpt
->macrotimer
= MACROPTIME
;
9712 rpt_mutex_unlock(&myrpt
->lock
);
9713 if (myrpt
->p
.archivedir
)
9717 sprintf(str
,"DTMF(M),MAIN,%c",c
);
9718 donodelog(myrpt
,str
);
9720 local_dtmf_helper(myrpt
,c
);
9721 } else rpt_mutex_unlock(&myrpt
->lock
);
9722 if (who
== myrpt
->rxchannel
) /* if it was a read from rx */
9726 f
= ast_read(myrpt
->rxchannel
);
9729 if (debug
) printf("@@@@ rpt:Hung Up\n");
9732 if (f
->frametype
== AST_FRAME_VOICE
)
9734 #ifdef _MDC_DECODE_H_
9735 unsigned char ubuf
[2560];
9740 if ((!myrpt
->localtx
) && (!myrpt
->p
.linktolink
)) {
9741 memset(f
->data
,0,f
->datalen
);
9744 #ifdef _MDC_DECODE_H_
9745 sp
= (short *) f
->data
;
9746 /* convert block to unsigned char */
9747 for(n
= 0; n
< f
->datalen
/ 2; n
++)
9749 ubuf
[n
] = (*sp
++ >> 8) + 128;
9751 n
= mdc_decoder_process_samples(myrpt
->mdc
,ubuf
,f
->datalen
/ 2);
9754 unsigned char op
,arg
;
9755 unsigned short unitID
;
9757 mdc_decoder_get_packet(myrpt
->mdc
,&op
,&arg
,&unitID
);
9760 ast_log(LOG_NOTICE
,"Got (single-length) packet:\n");
9761 ast_log(LOG_NOTICE
,"op: %02x, arg: %02x, UnitID: %04x\n",
9762 op
& 255,arg
& 255,unitID
);
9764 if ((op
== 1) && (arg
== 0))
9766 myrpt
->lastunit
= unitID
;
9767 mdc1200_notify(myrpt
,NULL
,myrpt
->lastunit
);
9768 mdc1200_send(myrpt
,myrpt
->lastunit
);
9771 if ((debug
> 2) && (i
== 2))
9773 unsigned char op
,arg
,ex1
,ex2
,ex3
,ex4
;
9774 unsigned short unitID
;
9776 mdc_decoder_get_double_packet(myrpt
->mdc
,&op
,&arg
,&unitID
,
9777 &ex1
,&ex2
,&ex3
,&ex4
);
9778 ast_log(LOG_NOTICE
,"Got (double-length) packet:\n");
9779 ast_log(LOG_NOTICE
,"op: %02x, arg: %02x, UnitID: %04x\n",
9780 op
& 255,arg
& 255,unitID
);
9781 ast_log(LOG_NOTICE
,"ex1: %02x, ex2: %02x, ex3: %02x, ex4: %02x\n",
9782 ex1
& 255, ex2
& 255, ex3
& 255, ex4
& 255);
9786 /* apply inbound filters, if any */
9787 rpt_filter(myrpt
,f
->data
,f
->datalen
/ 2);
9789 if (ioctl(myrpt
->zaprxchannel
->fds
[0], ZT_GETCONFMUTE
, &ismuted
) == -1)
9793 if (dtmfed
) ismuted
= 1;
9797 memset(f
->data
,0,f
->datalen
);
9799 memset(myrpt
->lastf1
->data
,0,myrpt
->lastf1
->datalen
);
9801 memset(myrpt
->lastf2
->data
,0,myrpt
->lastf2
->datalen
);
9803 if (f
) f2
= ast_frdup(f
);
9806 myrpt
->lastf2
= myrpt
->lastf1
;
9811 memset(myrpt
->lastf1
->data
,0,myrpt
->lastf1
->datalen
);
9813 memset(myrpt
->lastf2
->data
,0,myrpt
->lastf2
->datalen
);
9817 ast_write(myrpt
->pchannel
,f1
);
9821 #ifndef OLD_ASTERISK
9822 else if (f
->frametype
== AST_FRAME_DTMF_BEGIN
)
9825 memset(myrpt
->lastf1
->data
,0,myrpt
->lastf1
->datalen
);
9827 memset(myrpt
->lastf2
->data
,0,myrpt
->lastf2
->datalen
);
9831 else if (f
->frametype
== AST_FRAME_DTMF
)
9833 c
= (char) f
->subclass
; /* get DTMF char */
9836 memset(myrpt
->lastf1
->data
,0,myrpt
->lastf1
->datalen
);
9838 memset(myrpt
->lastf2
->data
,0,myrpt
->lastf2
->datalen
);
9840 if (!myrpt
->keyed
) continue;
9841 c
= func_xlat(myrpt
,c
,&myrpt
->p
.inxlat
);
9842 if (c
) local_dtmf_helper(myrpt
,c
);
9845 else if (f
->frametype
== AST_FRAME_CONTROL
)
9847 if (f
->subclass
== AST_CONTROL_HANGUP
)
9849 if (debug
) printf("@@@@ rpt:Hung Up\n");
9854 if (f
->subclass
== AST_CONTROL_RADIO_KEY
)
9856 if ((!lasttx
) || (myrpt
->p
.duplex
> 1) || (myrpt
->p
.linktolink
))
9858 if (debug
== 7) printf("@@@@ rx key\n");
9861 if (myrpt
->p
.archivedir
)
9863 donodelog(myrpt
,"RXKEY,MAIN");
9867 if (f
->subclass
== AST_CONTROL_RADIO_UNKEY
)
9869 if ((!lasttx
) || (myrpt
->p
.duplex
> 1) || (myrpt
->p
.linktolink
))
9871 if (debug
== 7) printf("@@@@ rx un-key\n");
9872 if(myrpt
->p
.duplex
&& myrpt
->keyed
) {
9873 rpt_telemetry(myrpt
,UNKEY
,NULL
);
9877 if (myrpt
->p
.archivedir
)
9879 donodelog(myrpt
,"RXUNKEY,MAIN");
9886 if (who
== myrpt
->pchannel
) /* if it was a read from pseudo */
9888 f
= ast_read(myrpt
->pchannel
);
9891 if (debug
) printf("@@@@ rpt:Hung Up\n");
9894 if (f
->frametype
== AST_FRAME_VOICE
)
9896 ast_write(myrpt
->txpchannel
,f
);
9898 if (f
->frametype
== AST_FRAME_CONTROL
)
9900 if (f
->subclass
== AST_CONTROL_HANGUP
)
9902 if (debug
) printf("@@@@ rpt:Hung Up\n");
9910 if (who
== myrpt
->txchannel
) /* if it was a read from tx */
9912 f
= ast_read(myrpt
->txchannel
);
9915 if (debug
) printf("@@@@ rpt:Hung Up\n");
9918 if (f
->frametype
== AST_FRAME_CONTROL
)
9920 if (f
->subclass
== AST_CONTROL_HANGUP
)
9922 if (debug
) printf("@@@@ rpt:Hung Up\n");
9930 if (who
== myrpt
->zaptxchannel
) /* if it was a read from pseudo-tx */
9932 f
= ast_read(myrpt
->zaptxchannel
);
9935 if (debug
) printf("@@@@ rpt:Hung Up\n");
9938 if (f
->frametype
== AST_FRAME_VOICE
)
9940 ast_write(myrpt
->txchannel
,f
);
9942 if (f
->frametype
== AST_FRAME_CONTROL
)
9944 if (f
->subclass
== AST_CONTROL_HANGUP
)
9946 if (debug
) printf("@@@@ rpt:Hung Up\n");
9955 rpt_mutex_lock(&myrpt
->lock
);
9956 l
= myrpt
->links
.next
;
9957 while(l
!= &myrpt
->links
)
9964 if (who
== l
->chan
) /* if it was a read from rx */
9969 /* see if any other links are receiving */
9970 m
= myrpt
->links
.next
;
9971 while(m
!= &myrpt
->links
)
9973 /* if not us, count it */
9974 if ((m
!= l
) && (m
->lastrx
)) remrx
= 1;
9977 rpt_mutex_unlock(&myrpt
->lock
);
9978 remnomute
= myrpt
->localtx
&&
9979 (!(myrpt
->cmdnode
[0] ||
9980 (myrpt
->dtmfidx
> -1)));
9981 totx
= (((l
->isremote
) ? (remnomute
) :
9982 myrpt
->exttx
) || remrx
) && l
->mode
;
9983 if (l
->phonemode
== 0 && l
->chan
&& (l
->lasttx
!= totx
))
9987 ast_indicate(l
->chan
,AST_CONTROL_RADIO_KEY
);
9991 ast_indicate(l
->chan
,AST_CONTROL_RADIO_UNKEY
);
9993 if (myrpt
->p
.archivedir
)
9998 sprintf(str
,"TXKEY,%s",l
->name
);
10000 sprintf(str
,"TXUNKEY,%s",l
->name
);
10001 donodelog(myrpt
,str
);
10005 f
= ast_read(l
->chan
);
10008 rpt_mutex_lock(&myrpt
->lock
);
10009 __kickshort(myrpt
);
10010 rpt_mutex_unlock(&myrpt
->lock
);
10011 if ((!l
->disced
) && (!l
->outbound
))
10013 if ((l
->name
[0] == '0') || l
->isremote
)
10016 l
->disctime
= DISC_TIME
;
10017 rpt_mutex_lock(&myrpt
->lock
);
10018 ast_hangup(l
->chan
);
10025 ast_hangup(l
->chan
);
10027 rpt_mutex_lock(&myrpt
->lock
);
10030 if (l
->outbound
&& (l
->retries
++ < l
->max_retries
) && (l
->hasconnected
))
10032 rpt_mutex_lock(&myrpt
->lock
);
10033 if (l
->chan
) ast_hangup(l
->chan
);
10035 l
->hasconnected
= 1;
10036 l
->retrytimer
= RETRY_TIMER_MS
;
10038 l
->connecttime
= 0;
10039 l
->thisconnected
= 0;
10042 rpt_mutex_lock(&myrpt
->lock
);
10043 /* remove from queue */
10044 remque((struct qelem
*) l
);
10045 if (!strcmp(myrpt
->cmdnode
,l
->name
))
10046 myrpt
->cmdnode
[0] = 0;
10047 __kickshort(myrpt
);
10048 rpt_mutex_unlock(&myrpt
->lock
);
10049 if (!l
->hasconnected
)
10050 rpt_telemetry(myrpt
,CONNFAIL
,l
);
10051 else if (l
->disced
!= 2) rpt_telemetry(myrpt
,REMDISC
,l
);
10052 if (myrpt
->p
.archivedir
)
10056 if (!l
->hasconnected
)
10057 sprintf(str
,"LINKFAIL,%s",l
->name
);
10059 sprintf(str
,"LINKDISC,%s",l
->name
);
10060 donodelog(myrpt
,str
);
10062 if (l
->lastf1
) ast_frfree(l
->lastf1
);
10064 if (l
->lastf2
) ast_frfree(l
->lastf2
);
10066 /* hang-up on call to device */
10067 ast_hangup(l
->chan
);
10068 ast_hangup(l
->pchan
);
10070 rpt_mutex_lock(&myrpt
->lock
);
10073 if (f
->frametype
== AST_FRAME_VOICE
)
10079 if (ioctl(l
->chan
->fds
[0], ZT_GETCONFMUTE
, &ismuted
) == -1)
10083 /* if not receiving, zero-out audio */
10084 ismuted
|= (!l
->lastrx
);
10085 if (l
->dtmfed
&& l
->phonemode
) ismuted
= 1;
10089 memset(f
->data
,0,f
->datalen
);
10091 memset(l
->lastf1
->data
,0,l
->lastf1
->datalen
);
10093 memset(l
->lastf2
->data
,0,l
->lastf2
->datalen
);
10095 if (f
) f2
= ast_frdup(f
);
10098 l
->lastf2
= l
->lastf1
;
10103 memset(l
->lastf1
->data
,0,l
->lastf1
->datalen
);
10105 memset(l
->lastf2
->data
,0,l
->lastf2
->datalen
);
10109 ast_write(l
->pchan
,f1
);
10116 memset(f
->data
,0,f
->datalen
);
10117 ast_write(l
->pchan
,f
);
10120 #ifndef OLD_ASTERISK
10121 else if (f
->frametype
== AST_FRAME_DTMF_BEGIN
)
10124 memset(l
->lastf1
->data
,0,l
->lastf1
->datalen
);
10126 memset(l
->lastf2
->data
,0,l
->lastf2
->datalen
);
10131 if (f
->frametype
== AST_FRAME_TEXT
)
10133 handle_link_data(myrpt
,l
,f
->data
);
10135 if (f
->frametype
== AST_FRAME_DTMF
)
10138 memset(l
->lastf1
->data
,0,l
->lastf1
->datalen
);
10140 memset(l
->lastf2
->data
,0,l
->lastf2
->datalen
);
10142 handle_link_phone_dtmf(myrpt
,l
,f
->subclass
);
10144 if (f
->frametype
== AST_FRAME_CONTROL
)
10146 if (f
->subclass
== AST_CONTROL_ANSWER
)
10148 char lconnected
= l
->connected
;
10150 __kickshort(myrpt
);
10152 l
->hasconnected
= 1;
10153 l
->thisconnected
= 1;
10155 if (!l
->isremote
) l
->retries
= 0;
10158 rpt_telemetry(myrpt
,CONNECTED
,l
);
10159 if (myrpt
->p
.archivedir
)
10164 sprintf(str
,"LINKTRX,%s",l
->name
);
10166 sprintf(str
,"LINKMONITOR,%s",l
->name
);
10167 donodelog(myrpt
,str
);
10174 if (f
->subclass
== AST_CONTROL_RADIO_KEY
)
10176 if (debug
== 7 ) printf("@@@@ rx key\n");
10179 if (myrpt
->p
.archivedir
&& (!l
->lastrx1
))
10184 sprintf(str
,"RXKEY,%s",l
->name
);
10185 donodelog(myrpt
,str
);
10189 if (f
->subclass
== AST_CONTROL_RADIO_UNKEY
)
10191 if (debug
== 7) printf("@@@@ rx un-key\n");
10194 if(myrpt
->p
.duplex
)
10195 rpt_telemetry(myrpt
,LINKUNKEY
,l
);
10196 if (myrpt
->p
.archivedir
&& (l
->lastrx1
))
10201 sprintf(str
,"RXUNKEY,%s",l
->name
);
10202 donodelog(myrpt
,str
);
10205 if (f
->subclass
== AST_CONTROL_HANGUP
)
10208 rpt_mutex_lock(&myrpt
->lock
);
10209 __kickshort(myrpt
);
10210 rpt_mutex_unlock(&myrpt
->lock
);
10211 if ((!l
->outbound
) && (!l
->disced
))
10213 if ((l
->name
[0] == '0') || l
->isremote
)
10216 l
->disctime
= DISC_TIME
;
10217 rpt_mutex_lock(&myrpt
->lock
);
10218 ast_hangup(l
->chan
);
10224 if (l
->chan
) ast_hangup(l
->chan
);
10226 rpt_mutex_lock(&myrpt
->lock
);
10229 if (l
->outbound
&& (l
->retries
++ < l
->max_retries
) && (l
->hasconnected
))
10231 rpt_mutex_lock(&myrpt
->lock
);
10232 if (l
->chan
) ast_hangup(l
->chan
);
10234 l
->hasconnected
= 1;
10236 l
->retrytimer
= RETRY_TIMER_MS
;
10237 l
->connecttime
= 0;
10238 l
->thisconnected
= 0;
10241 rpt_mutex_lock(&myrpt
->lock
);
10242 /* remove from queue */
10243 remque((struct qelem
*) l
);
10244 if (!strcmp(myrpt
->cmdnode
,l
->name
))
10245 myrpt
->cmdnode
[0] = 0;
10246 __kickshort(myrpt
);
10247 rpt_mutex_unlock(&myrpt
->lock
);
10248 if (!l
->hasconnected
)
10249 rpt_telemetry(myrpt
,CONNFAIL
,l
);
10250 else if (l
->disced
!= 2) rpt_telemetry(myrpt
,REMDISC
,l
);
10251 if (myrpt
->p
.archivedir
)
10255 if (!l
->hasconnected
)
10256 sprintf(str
,"LINKFAIL,%s",l
->name
);
10258 sprintf(str
,"LINKDISC,%s",l
->name
);
10259 donodelog(myrpt
,str
);
10261 if (l
->lastf1
) ast_frfree(l
->lastf1
);
10263 if (l
->lastf2
) ast_frfree(l
->lastf2
);
10265 /* hang-up on call to device */
10266 ast_hangup(l
->chan
);
10267 ast_hangup(l
->pchan
);
10269 rpt_mutex_lock(&myrpt
->lock
);
10274 rpt_mutex_lock(&myrpt
->lock
);
10277 if (who
== l
->pchan
)
10279 rpt_mutex_unlock(&myrpt
->lock
);
10280 f
= ast_read(l
->pchan
);
10283 if (debug
) printf("@@@@ rpt:Hung Up\n");
10285 rpt_mutex_lock(&myrpt
->lock
);
10288 if (f
->frametype
== AST_FRAME_VOICE
)
10290 if (l
->chan
) ast_write(l
->chan
,f
);
10292 if (f
->frametype
== AST_FRAME_CONTROL
)
10294 if (f
->subclass
== AST_CONTROL_HANGUP
)
10296 if (debug
) printf("@@@@ rpt:Hung Up\n");
10299 rpt_mutex_lock(&myrpt
->lock
);
10304 rpt_mutex_lock(&myrpt
->lock
);
10309 rpt_mutex_unlock(&myrpt
->lock
);
10311 if (who
== myrpt
->monchannel
)
10313 f
= ast_read(myrpt
->monchannel
);
10316 if (debug
) printf("@@@@ rpt:Hung Up\n");
10319 if (f
->frametype
== AST_FRAME_VOICE
)
10321 if (myrpt
->monstream
)
10322 ast_writestream(myrpt
->monstream
,f
);
10324 if (f
->frametype
== AST_FRAME_CONTROL
)
10326 if (f
->subclass
== AST_CONTROL_HANGUP
)
10328 if (debug
) printf("@@@@ rpt:Hung Up\n");
10336 if (who
== myrpt
->txpchannel
) /* if it was a read from remote tx */
10338 f
= ast_read(myrpt
->txpchannel
);
10341 if (debug
) printf("@@@@ rpt:Hung Up\n");
10344 if (f
->frametype
== AST_FRAME_CONTROL
)
10346 if (f
->subclass
== AST_CONTROL_HANGUP
)
10348 if (debug
) printf("@@@@ rpt:Hung Up\n");
10358 ast_hangup(myrpt
->pchannel
);
10359 ast_hangup(myrpt
->monchannel
);
10360 ast_hangup(myrpt
->txpchannel
);
10361 if (myrpt
->txchannel
!= myrpt
->rxchannel
) ast_hangup(myrpt
->txchannel
);
10362 if (myrpt
->zaptxchannel
!= myrpt
->txchannel
) ast_hangup(myrpt
->zaptxchannel
);
10363 if (myrpt
->lastf1
) ast_frfree(myrpt
->lastf1
);
10364 myrpt
->lastf1
= NULL
;
10365 if (myrpt
->lastf2
) ast_frfree(myrpt
->lastf2
);
10366 myrpt
->lastf2
= NULL
;
10367 ast_hangup(myrpt
->rxchannel
);
10368 rpt_mutex_lock(&myrpt
->lock
);
10369 l
= myrpt
->links
.next
;
10370 while(l
!= &myrpt
->links
)
10372 struct rpt_link
*ll
= l
;
10373 /* remove from queue */
10374 remque((struct qelem
*) l
);
10375 /* hang-up on call to device */
10376 if (l
->chan
) ast_hangup(l
->chan
);
10377 ast_hangup(l
->pchan
);
10381 rpt_mutex_unlock(&myrpt
->lock
);
10382 if (debug
) printf("@@@@ rpt:Hung up channel\n");
10383 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
10384 pthread_exit(NULL
);
10389 static void *rpt_master(void *ignore
)
10392 pthread_attr_t attr
;
10393 struct ast_config
*cfg
;
10396 /* init nodelog queue */
10397 nodelog
.next
= nodelog
.prev
= &nodelog
;
10398 /* go thru all the specified repeaters */
10401 /* wait until asterisk starts */
10402 while(!ast_test_flag(&ast_options
,AST_OPT_FLAG_FULLY_BOOTED
))
10404 rpt_vars
[n
].cfg
= ast_config_load("rpt.conf");
10405 cfg
= rpt_vars
[n
].cfg
;
10407 ast_log(LOG_NOTICE
, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
10408 pthread_exit(NULL
);
10410 while((this = ast_category_browse(cfg
,this)) != NULL
)
10412 for(i
= 0 ; i
< strlen(this) ; i
++){
10413 if((this[i
] < '0') || (this[i
] > '9'))
10416 if(i
!= strlen(this)) continue; /* Not a node defn */
10417 memset(&rpt_vars
[n
],0,sizeof(rpt_vars
[n
]));
10418 rpt_vars
[n
].name
= strdup(this);
10419 val
= (char *) ast_variable_retrieve(cfg
,this,"rxchannel");
10420 if (val
) rpt_vars
[n
].rxchanname
= strdup(val
);
10421 val
= (char *) ast_variable_retrieve(cfg
,this,"txchannel");
10422 if (val
) rpt_vars
[n
].txchanname
= strdup(val
);
10423 val
= (char *) ast_variable_retrieve(cfg
,this,"remote");
10424 if (val
) rpt_vars
[n
].remote
= strdup(val
);
10425 ast_mutex_init(&rpt_vars
[n
].lock
);
10426 ast_mutex_init(&rpt_vars
[n
].remlock
);
10427 rpt_vars
[n
].tele
.next
= &rpt_vars
[n
].tele
;
10428 rpt_vars
[n
].tele
.prev
= &rpt_vars
[n
].tele
;
10429 rpt_vars
[n
].rpt_thread
= AST_PTHREADT_NULL
;
10430 rpt_vars
[n
].tailmessagen
= 0;
10431 #ifdef _MDC_DECODE_H_
10432 rpt_vars
[n
].mdc
= mdc_decoder_new(8000);
10437 ast_config_destroy(cfg
);
10440 for(i
= 0; i
< n
; i
++)
10442 load_rpt_vars(i
,1);
10444 /* if is a remote, dont start one for it */
10445 if (rpt_vars
[i
].remote
)
10447 if(retreive_memory(&rpt_vars
[i
],"init")){ /* Try to retreive initial memory channel */
10448 strncpy(rpt_vars
[i
].freq
, "146.580", sizeof(rpt_vars
[i
].freq
) - 1);
10449 strncpy(rpt_vars
[i
].rxpl
, "100.0", sizeof(rpt_vars
[i
].rxpl
) - 1);
10451 strncpy(rpt_vars
[i
].txpl
, "100.0", sizeof(rpt_vars
[i
].txpl
) - 1);
10452 rpt_vars
[i
].remmode
= REM_MODE_FM
;
10453 rpt_vars
[i
].offset
= REM_SIMPLEX
;
10454 rpt_vars
[i
].powerlevel
= REM_MEDPWR
;
10458 if (!rpt_vars
[i
].p
.ident
)
10460 ast_log(LOG_WARNING
,"Did not specify ident for node %s\n",rpt_vars
[i
].name
);
10461 ast_config_destroy(cfg
);
10462 pthread_exit(NULL
);
10464 pthread_attr_init(&attr
);
10465 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
10466 ast_pthread_create(&rpt_vars
[i
].rpt_thread
,&attr
,rpt
,(void *) &rpt_vars
[i
]);
10472 /* Now monitor each thread, and restart it if necessary */
10473 for(i
= 0; i
< n
; i
++)
10476 if (rpt_vars
[i
].remote
) continue;
10477 if (rpt_vars
[i
].rpt_thread
== AST_PTHREADT_STOP
)
10480 rv
= pthread_kill(rpt_vars
[i
].rpt_thread
,0);
10483 if(time(NULL
) - rpt_vars
[i
].lastthreadrestarttime
<= 15)
10485 if(rpt_vars
[i
].threadrestarts
>= 5)
10487 ast_log(LOG_ERROR
,"Continual RPT thread restarts, killing Asterisk\n");
10488 exit(1); /* Stuck in a restart loop, kill Asterisk and start over */
10492 ast_log(LOG_NOTICE
,"RPT thread restarted on %s\n",rpt_vars
[i
].name
);
10493 rpt_vars
[i
].threadrestarts
++;
10497 rpt_vars
[i
].threadrestarts
= 0;
10499 rpt_vars
[i
].lastthreadrestarttime
= time(NULL
);
10500 pthread_attr_init(&attr
);
10501 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
10502 ast_pthread_create(&rpt_vars
[i
].rpt_thread
,&attr
,rpt
,(void *) &rpt_vars
[i
]);
10503 ast_log(LOG_WARNING
, "rpt_thread restarted on node %s\n", rpt_vars
[i
].name
);
10509 struct nodelog
*nodep
;
10510 char *space
,datestr
[100],fname
[300];
10513 ast_mutex_lock(&nodeloglock
);
10514 nodep
= nodelog
.next
;
10515 if(nodep
== &nodelog
) /* if nothing in queue */
10517 ast_mutex_unlock(&nodeloglock
);
10520 remque((struct qelem
*)nodep
);
10521 ast_mutex_unlock(&nodeloglock
);
10522 space
= strchr(nodep
->str
,' ');
10529 strftime(datestr
,sizeof(datestr
) - 1,"%Y%m%d",
10530 localtime(&nodep
->timestamp
));
10531 sprintf(fname
,"%s/%s/%s.txt",nodep
->archivedir
,
10532 nodep
->str
,datestr
);
10533 fd
= open(fname
,O_WRONLY
| O_CREAT
| O_APPEND
,0600);
10536 ast_log(LOG_ERROR
,"Cannot open node log file %s for write",space
+ 1);
10540 if (write(fd
,space
+ 1,strlen(space
+ 1)) !=
10543 ast_log(LOG_ERROR
,"Cannot write node log file %s for write",space
+ 1);
10552 ast_config_destroy(cfg
);
10553 pthread_exit(NULL
);
10556 static int rpt_exec(struct ast_channel
*chan
, void *data
)
10558 int res
=-1,i
,rem_totx
,rem_rx
,remkeyed
,n
,phone_mode
= 0;
10559 int iskenwood_pci4
,authtold
,authreq
,setting
,notremming
,reming
;
10560 int ismuted
,dtmfed
;
10561 #ifdef OLD_ASTERISK
10562 struct localuser
*u
;
10564 char tmp
[256], keyed
= 0,keyed1
= 0;
10565 char *options
,*stringp
,*tele
,c
;
10567 struct ast_frame
*f
,*f1
,*f2
;
10568 struct ast_channel
*who
;
10569 struct ast_channel
*cs
[20];
10570 struct rpt_link
*l
;
10571 ZT_CONFINFO ci
; /* conference info */
10573 int ms
,elap
,nullfd
;
10574 time_t t
,last_timeout_warning
;
10575 struct zt_radio_param z
;
10576 struct rpt_tele
*telem
;
10578 nullfd
= open("/dev/null",O_RDWR
);
10579 if (ast_strlen_zero(data
)) {
10580 ast_log(LOG_WARNING
, "Rpt requires an argument (system node)\n");
10584 strncpy(tmp
, (char *)data
, sizeof(tmp
)-1);
10586 /* if time has externally shifted negative, screw it */
10587 if (t
< starttime
) t
= starttime
+ START_DELAY
;
10588 if ((!starttime
) || (t
< (starttime
+ START_DELAY
)))
10590 ast_log(LOG_NOTICE
,"Node %s rejecting call: too soon!\n",tmp
);
10591 ast_safe_sleep(chan
,3000);
10595 strsep(&stringp
, "|");
10598 /* see if we can find our specified one */
10599 for(i
= 0; i
< nrpts
; i
++)
10601 /* if name matches, assign it and exit loop */
10602 if (!strcmp(tmp
,rpt_vars
[i
].name
))
10604 myrpt
= &rpt_vars
[i
];
10610 ast_log(LOG_WARNING
, "Cannot find specified system node %s\n",tmp
);
10614 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
){ /* Do not allow incoming connections if disabled */
10615 ast_log(LOG_NOTICE
, "Connect attempt to node %s with tx disabled", myrpt
->name
);
10619 /* if not phone access, must be an IAX connection */
10620 if (options
&& ((*options
== 'P') || (*options
== 'D') || (*options
== 'R')))
10625 if (*options
== 'D') phone_mode
= 2;
10626 ast_set_callerid(chan
,"0","app_rpt user","0");
10628 ast_channel_setoption(chan
,AST_OPTION_TONE_VERIFY
,&val
,sizeof(char),0);
10632 #ifdef ALLOW_LOCAL_CHANNELS
10633 /* Check to insure the connection is IAX2 or Local*/
10634 if ( (strncmp(chan
->name
,"IAX2",4)) && (strncmp(chan
->name
,"Local",5)) ) {
10635 ast_log(LOG_WARNING
, "We only accept links via IAX2 or Local!!\n");
10639 if (strncmp(chan
->name
,"IAX2",4))
10641 ast_log(LOG_WARNING
, "We only accept links via IAX2!!\n");
10646 if (options
&& (*options
== 'R'))
10649 /* Parts of this section taken from app_parkandannounce */
10650 char *return_context
;
10651 int l
, m
, lot
, timeout
= 0;
10652 char tmp
[256],*template;
10653 char *working
, *context
, *exten
, *priority
;
10657 rpt_mutex_lock(&myrpt
->lock
);
10658 m
= myrpt
->callmode
;
10659 rpt_mutex_unlock(&myrpt
->lock
);
10661 if ((!myrpt
->p
.nobusyout
) && m
)
10663 if (chan
->_state
!= AST_STATE_UP
)
10665 ast_indicate(chan
,AST_CONTROL_BUSY
);
10667 while(ast_safe_sleep(chan
,10000) != -1);
10671 if (chan
->_state
!= AST_STATE_UP
)
10676 l
=strlen(options
)+2;
10679 ast_log(LOG_WARNING
, "Out of memory\n");
10683 strncpy(s
,options
,l
);
10685 template=strsep(&s
,"|");
10687 ast_log(LOG_WARNING
, "An announce template must be defined\n");
10693 timeout
= atoi(strsep(&s
, "|"));
10697 return_context
= s
;
10699 if(return_context
!= NULL
) {
10700 /* set the return context. Code borrowed from the Goto builtin */
10702 working
= return_context
;
10703 context
= strsep(&working
, "|");
10704 exten
= strsep(&working
, "|");
10706 /* Only a priority in this one */
10707 priority
= context
;
10711 priority
= strsep(&working
, "|");
10713 /* Only an extension and priority in this one */
10719 if(atoi(priority
) < 0) {
10720 ast_log(LOG_WARNING
, "Priority '%s' must be a number > 0\n", priority
);
10724 /* At this point we have a priority and maybe an extension and a context */
10725 chan
->priority
= atoi(priority
);
10726 #ifdef OLD_ASTERISK
10727 if(exten
&& strcasecmp(exten
, "BYEXTENSION"))
10731 strncpy(chan
->exten
, exten
, sizeof(chan
->exten
)-1);
10733 strncpy(chan
->context
, context
, sizeof(chan
->context
)-1);
10734 } else { /* increment the priority by default*/
10738 if(option_verbose
> 2) {
10739 ast_verbose( VERBOSE_PREFIX_3
"Return Context: (%s,%s,%d) ID: %s\n", chan
->context
,chan
->exten
, chan
->priority
, chan
->cid
.cid_num
);
10740 if(!ast_exists_extension(chan
, chan
->context
, chan
->exten
, chan
->priority
, chan
->cid
.cid_num
)) {
10741 ast_verbose( VERBOSE_PREFIX_3
"Warning: Return Context Invalid, call will return to default|s\n");
10745 /* we are using masq_park here to protect * from touching the channel once we park it. If the channel comes out of timeout
10746 before we are done announcing and the channel is messed with, Kablooeee. So we use Masq to prevent this. */
10748 ast_masq_park_call(chan
, NULL
, timeout
, &lot
);
10750 if (option_verbose
> 2) ast_verbose( VERBOSE_PREFIX_3
"Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot
, timeout
, return_context
);
10752 snprintf(tmp
,sizeof(tmp
) - 1,"%d,%s",lot
,template + 1);
10754 rpt_telemetry(myrpt
,REV_PATCH
,tmp
);
10764 struct ast_hostent ahp
;
10765 struct hostent
*hp
;
10767 char hisip
[100],nodeip
[100],*val
, *s
, *s1
, *s2
, *b
,*b1
;
10769 /* look at callerid to see what node this comes from */
10770 if (!chan
->cid
.cid_num
) /* if doesn't have caller id */
10772 ast_log(LOG_WARNING
, "Doesnt have callerid on %s\n",tmp
);
10776 /* get his IP from IAX2 module */
10777 memset(hisip
,0,sizeof(hisip
));
10778 #ifdef ALLOW_LOCAL_CHANNELS
10779 /* set IP address if this is a local connection*/
10780 if (strncmp(chan
->name
,"Local",5)==0) {
10781 strcpy(hisip
,"127.0.0.1");
10783 pbx_substitute_variables_helper(chan
,"${IAXPEER(CURRENTCHANNEL)}",hisip
,sizeof(hisip
) - 1);
10786 pbx_substitute_variables_helper(chan
,"${IAXPEER(CURRENTCHANNEL)}",hisip
,sizeof(hisip
) - 1);
10791 ast_log(LOG_WARNING
, "Link IP address cannot be determined!!\n");
10795 ast_callerid_parse(chan
->cid
.cid_num
,&b
,&b1
);
10796 ast_shrink_phone_number(b1
);
10797 if (!strcmp(myrpt
->name
,b1
))
10799 ast_log(LOG_WARNING
, "Trying to link to self!!\n");
10805 ast_log(LOG_WARNING
, "Node %s Invalid for connection here!!\n",b1
);
10810 /* look for his reported node string */
10811 val
= node_lookup(myrpt
,b1
);
10814 ast_log(LOG_WARNING
, "Reported node %s cannot be found!!\n",b1
);
10817 strncpy(tmp
,val
,sizeof(tmp
) - 1);
10819 s1
= strsep(&s
,",");
10820 s2
= strsep(&s
,",");
10823 ast_log(LOG_WARNING
, "Reported node %s not in correct format!!\n",b1
);
10826 if (strcmp(s2
,"NONE")) {
10827 hp
= ast_gethostbyname(s2
, &ahp
);
10830 ast_log(LOG_WARNING
, "Reported node %s, name %s cannot be found!!\n",b1
,s2
);
10833 memcpy(&ia
,hp
->h_addr
,sizeof(in_addr_t
));
10834 #ifdef OLD_ASTERISK
10835 ast_inet_ntoa(nodeip
,sizeof(nodeip
) - 1,ia
);
10837 strncpy(nodeip
,ast_inet_ntoa(ia
),sizeof(nodeip
) - 1);
10839 if (strcmp(hisip
,nodeip
))
10841 char *s3
= strchr(s1
,'@');
10842 if (s3
) s1
= s3
+ 1;
10843 s3
= strchr(s1
,'/');
10845 hp
= ast_gethostbyname(s1
, &ahp
);
10848 ast_log(LOG_WARNING
, "Reported node %s, name %s cannot be found!!\n",b1
,s1
);
10851 memcpy(&ia
,hp
->h_addr
,sizeof(in_addr_t
));
10852 #ifdef OLD_ASTERISK
10853 ast_inet_ntoa(nodeip
,sizeof(nodeip
) - 1,ia
);
10855 strncpy(nodeip
,ast_inet_ntoa(ia
),sizeof(nodeip
) - 1);
10857 if (strcmp(hisip
,nodeip
))
10859 ast_log(LOG_WARNING
, "Node %s IP %s does not match link IP %s!!\n",b1
,nodeip
,hisip
);
10866 /* if is not a remote */
10867 if (!myrpt
->remote
)
10871 int reconnects
= 0;
10873 /* look at callerid to see what node this comes from */
10874 if (!chan
->cid
.cid_num
) /* if doesn't have caller id */
10876 ast_log(LOG_WARNING
, "Doesnt have callerid on %s\n",tmp
);
10880 ast_callerid_parse(chan
->cid
.cid_num
,&b
,&b1
);
10881 ast_shrink_phone_number(b1
);
10882 if (!strcmp(myrpt
->name
,b1
))
10884 ast_log(LOG_WARNING
, "Trying to link to self!!\n");
10887 rpt_mutex_lock(&myrpt
->lock
);
10888 l
= myrpt
->links
.next
;
10889 /* try to find this one in queue */
10890 while(l
!= &myrpt
->links
)
10892 if (l
->name
[0] == '0')
10897 /* if found matching string */
10898 if (!strcmp(l
->name
,b1
)) break;
10902 if (l
!= &myrpt
->links
)
10905 l
->retries
= l
->max_retries
+ 1;
10907 reconnects
= l
->reconnects
;
10909 rpt_mutex_unlock(&myrpt
->lock
);
10912 rpt_mutex_unlock(&myrpt
->lock
);
10913 /* establish call in tranceive mode */
10914 l
= malloc(sizeof(struct rpt_link
));
10917 ast_log(LOG_WARNING
, "Unable to malloc\n");
10918 pthread_exit(NULL
);
10920 /* zero the silly thing */
10921 memset((char *)l
,0,sizeof(struct rpt_link
));
10923 strncpy(l
->name
,b1
,MAXNODESTR
- 1);
10927 l
->thisconnected
= 1;
10928 l
->hasconnected
= 1;
10929 l
->reconnects
= reconnects
;
10930 l
->phonemode
= phone_mode
;
10934 ast_set_read_format(l
->chan
,AST_FORMAT_SLINEAR
);
10935 ast_set_write_format(l
->chan
,AST_FORMAT_SLINEAR
);
10936 /* allocate a pseudo-channel thru asterisk */
10937 l
->pchan
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
10940 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
10941 pthread_exit(NULL
);
10943 ast_set_read_format(l
->pchan
,AST_FORMAT_SLINEAR
);
10944 ast_set_write_format(l
->pchan
,AST_FORMAT_SLINEAR
);
10945 #ifdef AST_CDR_FLAG_POST_DISABLED
10946 ast_set_flag(l
->pchan
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
10948 /* make a conference for the tx */
10950 ci
.confno
= myrpt
->conf
;
10951 ci
.confmode
= ZT_CONF_CONF
| ZT_CONF_LISTENER
| ZT_CONF_TALKER
;
10952 /* first put the channel on the conference in proper mode */
10953 if (ioctl(l
->pchan
->fds
[0],ZT_SETCONF
,&ci
) == -1)
10955 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
10956 pthread_exit(NULL
);
10958 rpt_mutex_lock(&myrpt
->lock
);
10959 if (phone_mode
> 1) l
->lastrx
= 1;
10960 l
->max_retries
= MAX_RETRIES
;
10961 /* insert at end of queue */
10962 insque((struct qelem
*)l
,(struct qelem
*)myrpt
->links
.next
);
10963 __kickshort(myrpt
);
10964 rpt_mutex_unlock(&myrpt
->lock
);
10965 if (chan
->_state
!= AST_STATE_UP
) {
10968 if (myrpt
->p
.archivedir
)
10973 sprintf(str
,"LINK(P),%s",l
->name
);
10975 sprintf(str
,"LINK,%s",l
->name
);
10976 donodelog(myrpt
,str
);
10978 return AST_PBX_KEEPALIVE
;
10980 /* well, then it is a remote */
10981 rpt_mutex_lock(&myrpt
->lock
);
10982 /* if remote, error if anyone else already linked */
10983 if (myrpt
->remoteon
)
10985 rpt_mutex_unlock(&myrpt
->lock
);
10987 if (myrpt
->remoteon
)
10989 ast_log(LOG_WARNING
, "Trying to use busy link on %s\n",tmp
);
10992 rpt_mutex_lock(&myrpt
->lock
);
10994 if ((!strcmp(myrpt
->remote
, remote_rig_rbi
)) &&
10995 (ioperm(myrpt
->p
.iobase
,1,1) == -1))
10997 rpt_mutex_unlock(&myrpt
->lock
);
10998 ast_log(LOG_WARNING
, "Cant get io permission on IO port %x hex\n",myrpt
->p
.iobase
);
11001 myrpt
->remoteon
= 1;
11002 #ifdef OLD_ASTERISK
11005 rpt_mutex_unlock(&myrpt
->lock
);
11006 /* find our index, and load the vars initially */
11007 for(i
= 0; i
< nrpts
; i
++)
11009 if (&rpt_vars
[i
] == myrpt
)
11011 load_rpt_vars(i
,0);
11015 rpt_mutex_lock(&myrpt
->lock
);
11016 tele
= strchr(myrpt
->rxchanname
,'/');
11019 fprintf(stderr
,"rpt:Dial number must be in format tech/number\n");
11020 rpt_mutex_unlock(&myrpt
->lock
);
11021 pthread_exit(NULL
);
11024 myrpt
->rxchannel
= ast_request(myrpt
->rxchanname
,AST_FORMAT_SLINEAR
,tele
,NULL
);
11025 myrpt
->zaprxchannel
= NULL
;
11026 if (!strcasecmp(myrpt
->rxchanname
,"Zap"))
11027 myrpt
->zaprxchannel
= myrpt
->rxchannel
;
11028 if (myrpt
->rxchannel
)
11030 ast_set_read_format(myrpt
->rxchannel
,AST_FORMAT_SLINEAR
);
11031 ast_set_write_format(myrpt
->rxchannel
,AST_FORMAT_SLINEAR
);
11032 #ifdef AST_CDR_FLAG_POST_DISABLED
11033 ast_set_flag(myrpt
->rxchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
11035 myrpt
->rxchannel
->whentohangup
= 0;
11036 myrpt
->rxchannel
->appl
= "Apprpt";
11037 myrpt
->rxchannel
->data
= "(Link Rx)";
11038 if (option_verbose
> 2)
11039 ast_verbose(VERBOSE_PREFIX_3
"rpt (Rx) initiating call to %s/%s on %s\n",
11040 myrpt
->rxchanname
,tele
,myrpt
->rxchannel
->name
);
11041 rpt_mutex_unlock(&myrpt
->lock
);
11042 ast_call(myrpt
->rxchannel
,tele
,999);
11043 rpt_mutex_lock(&myrpt
->lock
);
11047 fprintf(stderr
,"rpt:Sorry unable to obtain Rx channel\n");
11048 rpt_mutex_unlock(&myrpt
->lock
);
11049 pthread_exit(NULL
);
11052 myrpt
->zaptxchannel
= NULL
;
11053 if (myrpt
->txchanname
)
11055 tele
= strchr(myrpt
->txchanname
,'/');
11058 fprintf(stderr
,"rpt:Dial number must be in format tech/number\n");
11059 rpt_mutex_unlock(&myrpt
->lock
);
11060 ast_hangup(myrpt
->rxchannel
);
11061 pthread_exit(NULL
);
11064 myrpt
->txchannel
= ast_request(myrpt
->txchanname
,AST_FORMAT_SLINEAR
,tele
,NULL
);
11065 if (!strcasecmp(myrpt
->txchanname
,"Zap"))
11066 myrpt
->zaptxchannel
= myrpt
->txchannel
;
11067 if (myrpt
->txchannel
)
11069 ast_set_read_format(myrpt
->txchannel
,AST_FORMAT_SLINEAR
);
11070 ast_set_write_format(myrpt
->txchannel
,AST_FORMAT_SLINEAR
);
11071 #ifdef AST_CDR_FLAG_POST_DISABLED
11072 ast_set_flag(myrpt
->txchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
11074 myrpt
->txchannel
->whentohangup
= 0;
11075 myrpt
->txchannel
->appl
= "Apprpt";
11076 myrpt
->txchannel
->data
= "(Link Tx)";
11077 if (option_verbose
> 2)
11078 ast_verbose(VERBOSE_PREFIX_3
"rpt (Tx) initiating call to %s/%s on %s\n",
11079 myrpt
->txchanname
,tele
,myrpt
->txchannel
->name
);
11080 rpt_mutex_unlock(&myrpt
->lock
);
11081 ast_call(myrpt
->txchannel
,tele
,999);
11082 rpt_mutex_lock(&myrpt
->lock
);
11086 fprintf(stderr
,"rpt:Sorry unable to obtain Tx channel\n");
11087 rpt_mutex_unlock(&myrpt
->lock
);
11088 ast_hangup(myrpt
->rxchannel
);
11089 pthread_exit(NULL
);
11095 myrpt
->txchannel
= myrpt
->rxchannel
;
11097 /* allocate a pseudo-channel thru asterisk */
11098 myrpt
->pchannel
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
11099 if (!myrpt
->pchannel
)
11101 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
11102 rpt_mutex_unlock(&myrpt
->lock
);
11103 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
11104 ast_hangup(myrpt
->txchannel
);
11105 ast_hangup(myrpt
->rxchannel
);
11106 pthread_exit(NULL
);
11108 ast_set_read_format(myrpt
->pchannel
,AST_FORMAT_SLINEAR
);
11109 ast_set_write_format(myrpt
->pchannel
,AST_FORMAT_SLINEAR
);
11110 #ifdef AST_CDR_FLAG_POST_DISABLED
11111 ast_set_flag(myrpt
->pchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
11113 if (!myrpt
->zaprxchannel
) myrpt
->zaprxchannel
= myrpt
->pchannel
;
11114 if (!myrpt
->zaptxchannel
) myrpt
->zaptxchannel
= myrpt
->pchannel
;
11115 /* make a conference for the pseudo */
11117 ci
.confno
= -1; /* make a new conf */
11118 ci
.confmode
= ZT_CONF_CONFANNMON
;
11119 /* first put the channel on the conference in announce/monitor mode */
11120 if (ioctl(myrpt
->pchannel
->fds
[0],ZT_SETCONF
,&ci
) == -1)
11122 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
11123 rpt_mutex_unlock(&myrpt
->lock
);
11124 ast_hangup(myrpt
->pchannel
);
11125 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
11126 ast_hangup(myrpt
->txchannel
);
11127 ast_hangup(myrpt
->rxchannel
);
11128 pthread_exit(NULL
);
11130 /* save pseudo channel conference number */
11131 myrpt
->conf
= myrpt
->txconf
= ci
.confno
;
11132 /* if serial io port, open it */
11134 if (myrpt
->p
.ioport
&& ((myrpt
->iofd
= openserial(myrpt
->p
.ioport
)) == -1))
11136 rpt_mutex_unlock(&myrpt
->lock
);
11137 ast_hangup(myrpt
->pchannel
);
11138 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
11139 ast_hangup(myrpt
->txchannel
);
11140 ast_hangup(myrpt
->rxchannel
);
11141 pthread_exit(NULL
);
11143 iskenwood_pci4
= 0;
11144 memset(&z
,0,sizeof(z
));
11145 if ((myrpt
->iofd
< 1) && (myrpt
->txchannel
== myrpt
->zaptxchannel
))
11147 z
.radpar
= ZT_RADPAR_REMMODE
;
11148 z
.data
= ZT_RADPAR_REM_NONE
;
11149 res
= ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&z
);
11150 /* if PCIRADIO and kenwood selected */
11151 if ((!res
) && (!strcmp(myrpt
->remote
,remote_rig_kenwood
)))
11153 z
.radpar
= ZT_RADPAR_UIOMODE
;
11155 if (ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&z
) == -1)
11157 ast_log(LOG_ERROR
,"Cannot set UIOMODE\n");
11160 z
.radpar
= ZT_RADPAR_UIODATA
;
11162 if (ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&z
) == -1)
11164 ast_log(LOG_ERROR
,"Cannot set UIODATA\n");
11168 if (ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_HOOK
,&i
) == -1)
11170 ast_log(LOG_ERROR
,"Cannot set hook\n");
11173 iskenwood_pci4
= 1;
11176 if (myrpt
->txchannel
== myrpt
->zaptxchannel
)
11179 ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_HOOK
,&i
);
11180 /* if PCIRADIO and Yaesu ft897/ICOM IC-706 selected */
11181 if ((myrpt
->iofd
< 1) && (!res
) &&
11182 (!strcmp(myrpt
->remote
,remote_rig_ft897
) ||
11183 (!strcmp(myrpt
->remote
,remote_rig_ic706
))))
11185 z
.radpar
= ZT_RADPAR_UIOMODE
;
11187 if (ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&z
) == -1)
11189 ast_log(LOG_ERROR
,"Cannot set UIOMODE\n");
11192 z
.radpar
= ZT_RADPAR_UIODATA
;
11194 if (ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&z
) == -1)
11196 ast_log(LOG_ERROR
,"Cannot set UIODATA\n");
11201 myrpt
->remoterx
= 0;
11202 myrpt
->remotetx
= 0;
11203 myrpt
->retxtimer
= 0;
11204 myrpt
->rerxtimer
= 0;
11205 myrpt
->remoteon
= 1;
11206 myrpt
->dtmfidx
= -1;
11207 myrpt
->dtmfbuf
[0] = 0;
11208 myrpt
->dtmf_time_rem
= 0;
11209 myrpt
->hfscanmode
= 0;
11210 myrpt
->hfscanstatus
= 0;
11211 if (myrpt
->p
.startupmacro
)
11213 snprintf(myrpt
->macrobuf
,MAXMACRO
- 1,"PPPP%s",myrpt
->p
.startupmacro
);
11215 time(&myrpt
->start_time
);
11216 myrpt
->last_activity_time
= myrpt
->start_time
;
11217 last_timeout_warning
= 0;
11219 myrpt
->tele
.next
= &myrpt
->tele
;
11220 myrpt
->tele
.prev
= &myrpt
->tele
;
11221 rpt_mutex_unlock(&myrpt
->lock
);
11222 ast_set_write_format(chan
, AST_FORMAT_SLINEAR
);
11223 ast_set_read_format(chan
, AST_FORMAT_SLINEAR
);
11226 /* if we are on 2w loop and are a remote, turn EC on */
11227 if (myrpt
->remote
&& (myrpt
->rxchannel
== myrpt
->txchannel
))
11230 ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_ECHOCANCEL
,&i
);
11232 if (chan
->_state
!= AST_STATE_UP
) {
11236 if (myrpt
->rxchannel
== myrpt
->zaprxchannel
)
11238 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_GET_PARAMS
,&par
) != -1)
11240 if (par
.rxisoffhook
)
11242 ast_indicate(chan
,AST_CONTROL_RADIO_KEY
);
11243 myrpt
->remoterx
= 1;
11248 if (myrpt
->p
.archivedir
)
11250 char mycmd
[100],mydate
[100],*b
,*b1
;
11255 mkdir(myrpt
->p
.archivedir
,0600);
11256 sprintf(mycmd
,"%s/%s",myrpt
->p
.archivedir
,myrpt
->name
);
11259 strftime(mydate
,sizeof(mydate
) - 1,"%Y%m%d%H%M%S",
11261 sprintf(mycmd
,"mixmonitor start %s %s/%s/%s.wav49 a",chan
->name
,
11262 myrpt
->p
.archivedir
,myrpt
->name
,mydate
);
11263 if (myrpt
->p
.monminblocks
)
11265 blocksleft
= diskavail(myrpt
);
11266 if (myrpt
->p
.remotetimeout
)
11268 blocksleft
-= (myrpt
->p
.remotetimeout
*
11269 MONITOR_DISK_BLOCKS_PER_MINUTE
) / 60;
11271 if (blocksleft
>= myrpt
->p
.monminblocks
)
11272 ast_cli_command(nullfd
,mycmd
);
11273 } else ast_cli_command(nullfd
,mycmd
);
11274 /* look at callerid to see what node this comes from */
11275 if (!chan
->cid
.cid_num
) /* if doesn't have caller id */
11279 ast_callerid_parse(chan
->cid
.cid_num
,&b
,&b1
);
11280 ast_shrink_phone_number(b1
);
11282 sprintf(mycmd
,"CONNECT,%s",b1
);
11283 donodelog(myrpt
,mycmd
);
11285 myrpt
->loginuser
[0] = 0;
11286 myrpt
->loginlevel
[0] = 0;
11287 myrpt
->authtelltimer
= 0;
11288 myrpt
->authtimer
= 0;
11291 if (myrpt
->p
.authlevel
> 1) authreq
= 1;
11296 cs
[n
++] = myrpt
->rxchannel
;
11297 cs
[n
++] = myrpt
->pchannel
;
11298 if (myrpt
->rxchannel
!= myrpt
->txchannel
)
11299 cs
[n
++] = myrpt
->txchannel
;
11300 /* start un-locked */
11303 if (ast_check_hangup(chan
)) break;
11304 if (ast_check_hangup(myrpt
->rxchannel
)) break;
11308 telem
= myrpt
->tele
.next
;
11309 while(telem
!= &myrpt
->tele
)
11311 if (telem
->mode
== SETREMOTE
) setting
= 1;
11312 if ((telem
->mode
== SETREMOTE
) ||
11313 (telem
->mode
== SCAN
) ||
11314 (telem
->mode
== TUNE
)) reming
= 1;
11315 else notremming
= 1;
11316 telem
= telem
->next
;
11321 /* find our index, and load the vars */
11322 for(i
= 0; i
< nrpts
; i
++)
11324 if (&rpt_vars
[i
] == myrpt
)
11326 load_rpt_vars(i
,0);
11332 if (myrpt
->p
.remotetimeout
)
11336 r
= (t
- myrpt
->start_time
);
11337 if (r
>= myrpt
->p
.remotetimeout
)
11339 sayfile(chan
,"rpt/node");
11340 ast_say_character_str(chan
,myrpt
->name
,NULL
,chan
->language
);
11341 sayfile(chan
,"rpt/timeout");
11342 ast_safe_sleep(chan
,1000);
11345 if ((myrpt
->p
.remotetimeoutwarning
) &&
11346 (r
>= (myrpt
->p
.remotetimeout
-
11347 myrpt
->p
.remotetimeoutwarning
)) &&
11348 (r
<= (myrpt
->p
.remotetimeout
-
11349 myrpt
->p
.remotetimeoutwarningfreq
)))
11351 if (myrpt
->p
.remotetimeoutwarningfreq
)
11353 if ((t
- last_timeout_warning
) >=
11354 myrpt
->p
.remotetimeoutwarningfreq
)
11356 time(&last_timeout_warning
);
11357 rpt_telemetry(myrpt
,TIMEOUT_WARNING
,0);
11362 if (!last_timeout_warning
)
11364 time(&last_timeout_warning
);
11365 rpt_telemetry(myrpt
,TIMEOUT_WARNING
,0);
11370 if (myrpt
->p
.remoteinacttimeout
&& myrpt
->last_activity_time
)
11374 r
= (t
- myrpt
->last_activity_time
);
11375 if (r
>= myrpt
->p
.remoteinacttimeout
)
11377 sayfile(chan
,"rpt/node");
11378 ast_say_character_str(chan
,myrpt
->name
,NULL
,chan
->language
);
11379 sayfile(chan
,"rpt/timeout");
11380 ast_safe_sleep(chan
,1000);
11383 if ((myrpt
->p
.remotetimeoutwarning
) &&
11384 (r
>= (myrpt
->p
.remoteinacttimeout
-
11385 myrpt
->p
.remotetimeoutwarning
)) &&
11386 (r
<= (myrpt
->p
.remoteinacttimeout
-
11387 myrpt
->p
.remotetimeoutwarningfreq
)))
11389 if (myrpt
->p
.remotetimeoutwarningfreq
)
11391 if ((t
- last_timeout_warning
) >=
11392 myrpt
->p
.remotetimeoutwarningfreq
)
11394 time(&last_timeout_warning
);
11395 rpt_telemetry(myrpt
,ACT_TIMEOUT_WARNING
,0);
11400 if (!last_timeout_warning
)
11402 time(&last_timeout_warning
);
11403 rpt_telemetry(myrpt
,ACT_TIMEOUT_WARNING
,0);
11409 who
= ast_waitfor_n(cs
,n
,&ms
);
11410 if (who
== NULL
) ms
= 0;
11411 elap
= MSWAIT
- ms
;
11412 if (myrpt
->macrotimer
) myrpt
->macrotimer
-= elap
;
11413 if (myrpt
->macrotimer
< 0) myrpt
->macrotimer
= 0;
11415 /* do local dtmf timer */
11416 if (myrpt
->dtmf_local_timer
)
11418 if (myrpt
->dtmf_local_timer
> 1) myrpt
->dtmf_local_timer
-= elap
;
11419 if (myrpt
->dtmf_local_timer
< 1) myrpt
->dtmf_local_timer
= 1;
11421 rpt_mutex_lock(&myrpt
->lock
);
11422 do_dtmf_local(myrpt
,0);
11423 rpt_mutex_unlock(&myrpt
->lock
);
11424 rem_totx
= myrpt
->dtmf_local_timer
&& (!phone_mode
);
11425 rem_totx
|= keyed
&& (!myrpt
->tunerequest
);
11426 rem_rx
= (remkeyed
&& (!setting
)) || (myrpt
->tele
.next
!= &myrpt
->tele
);
11427 if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
11428 rem_totx
|= myrpt
->tunerequest
;
11429 if (keyed
&& (!keyed1
))
11434 if (!keyed
&& (keyed1
))
11440 /* if login necessary, and not too soon */
11441 if ((myrpt
->p
.authlevel
) &&
11442 (!myrpt
->loginlevel
[0]) &&
11447 myrpt
->authtelltimer
= AUTHTELLTIME
- AUTHTXTIME
;
11452 if (rem_rx
&& (!myrpt
->remoterx
))
11454 myrpt
->remoterx
= 1;
11455 ast_indicate(chan
,AST_CONTROL_RADIO_KEY
);
11457 if ((!rem_rx
) && (myrpt
->remoterx
))
11459 myrpt
->remoterx
= 0;
11460 ast_indicate(chan
,AST_CONTROL_RADIO_UNKEY
);
11462 /* if auth requested, and not authed yet */
11463 if (authreq
&& (!myrpt
->loginlevel
[0]))
11465 if ((!authtold
) && ((myrpt
->authtelltimer
+= elap
)
11469 rpt_telemetry(myrpt
,LOGINREQ
,NULL
);
11471 if ((myrpt
->authtimer
+= elap
) >= AUTHLOGOUTTIME
)
11473 break; /* if not logged in, hang up after a time */
11477 if ((myrpt
->retxtimer
+= elap
) >= REDUNDANT_TX_TIME
)
11479 myrpt
->retxtimer
= 0;
11480 if ((myrpt
->remoterx
) && (!myrpt
->remotetx
))
11481 ast_indicate(chan
,AST_CONTROL_RADIO_KEY
);
11483 ast_indicate(chan
,AST_CONTROL_RADIO_UNKEY
);
11486 if ((myrpt
->rerxtimer
+= elap
) >= (REDUNDANT_TX_TIME
* 2))
11489 myrpt
->rerxtimer
= 0;
11492 if (rem_totx
&& (!myrpt
->remotetx
))
11494 /* if not authed, and needed, dont transmit */
11495 if ((!myrpt
->p
.authlevel
) || myrpt
->loginlevel
[0])
11497 myrpt
->remotetx
= 1;
11498 if((myrpt
->remtxfreqok
= check_tx_freq(myrpt
)))
11500 time(&myrpt
->last_activity_time
);
11501 if ((iskenwood_pci4
) && (myrpt
->txchannel
== myrpt
->zaptxchannel
))
11503 z
.radpar
= ZT_RADPAR_UIODATA
;
11505 if (ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&z
) == -1)
11507 ast_log(LOG_ERROR
,"Cannot set UIODATA\n");
11513 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_KEY
);
11515 if (myrpt
->p
.archivedir
) donodelog(myrpt
,"TXKEY");
11519 if ((!rem_totx
) && myrpt
->remotetx
) /* Remote base radio TX unkey */
11521 myrpt
->remotetx
= 0;
11522 if(!myrpt
->remtxfreqok
){
11523 rpt_telemetry(myrpt
,UNAUTHTX
,NULL
);
11525 if ((iskenwood_pci4
) && (myrpt
->txchannel
== myrpt
->zaptxchannel
))
11527 z
.radpar
= ZT_RADPAR_UIODATA
;
11529 if (ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&z
) == -1)
11531 ast_log(LOG_ERROR
,"Cannot set UIODATA\n");
11537 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_UNKEY
);
11539 if (myrpt
->p
.archivedir
) donodelog(myrpt
,"TXUNKEY");
11541 if (myrpt
->hfscanmode
){
11542 myrpt
->scantimer
-= elap
;
11543 if(myrpt
->scantimer
<= 0){
11546 myrpt
->scantimer
= REM_SCANTIME
;
11547 rpt_telemetry(myrpt
,SCAN
,0);
11548 } else myrpt
->scantimer
= 1;
11551 rpt_mutex_lock(&myrpt
->lock
);
11552 c
= myrpt
->macrobuf
[0];
11553 if (c
&& (!myrpt
->macrotimer
))
11555 myrpt
->macrotimer
= MACROTIME
;
11556 memmove(myrpt
->macrobuf
,myrpt
->macrobuf
+ 1,MAXMACRO
- 1);
11557 if ((c
== 'p') || (c
== 'P'))
11558 myrpt
->macrotimer
= MACROPTIME
;
11559 rpt_mutex_unlock(&myrpt
->lock
);
11560 if (myrpt
->p
.archivedir
)
11563 sprintf(str
,"DTMF(M),%c",c
);
11564 donodelog(myrpt
,str
);
11566 if (handle_remote_dtmf_digit(myrpt
,c
,&keyed
,0) == -1) break;
11568 } else rpt_mutex_unlock(&myrpt
->lock
);
11569 if (who
== chan
) /* if it was a read from incomming */
11571 f
= ast_read(chan
);
11574 if (debug
) printf("@@@@ link:Hung Up\n");
11577 if (f
->frametype
== AST_FRAME_VOICE
)
11579 if (ioctl(chan
->fds
[0], ZT_GETCONFMUTE
, &ismuted
) == -1)
11583 /* if not transmitting, zero-out audio */
11584 ismuted
|= (!myrpt
->remotetx
);
11585 if (dtmfed
&& phone_mode
) ismuted
= 1;
11589 memset(f
->data
,0,f
->datalen
);
11591 memset(myrpt
->lastf1
->data
,0,myrpt
->lastf1
->datalen
);
11593 memset(myrpt
->lastf2
->data
,0,myrpt
->lastf2
->datalen
);
11595 if (f
) f2
= ast_frdup(f
);
11597 f1
= myrpt
->lastf2
;
11598 myrpt
->lastf2
= myrpt
->lastf1
;
11599 myrpt
->lastf1
= f2
;
11603 memset(myrpt
->lastf1
->data
,0,myrpt
->lastf1
->datalen
);
11605 memset(myrpt
->lastf2
->data
,0,myrpt
->lastf2
->datalen
);
11610 ast_write(myrpt
->txchannel
,f1
);
11612 ast_write(myrpt
->txchannel
,f
);
11616 #ifndef OLD_ASTERISK
11617 else if (f
->frametype
== AST_FRAME_DTMF_BEGIN
)
11620 memset(myrpt
->lastf1
->data
,0,myrpt
->lastf1
->datalen
);
11622 memset(myrpt
->lastf2
->data
,0,myrpt
->lastf2
->datalen
);
11626 if (f
->frametype
== AST_FRAME_DTMF
)
11629 memset(myrpt
->lastf1
->data
,0,myrpt
->lastf1
->datalen
);
11631 memset(myrpt
->lastf2
->data
,0,myrpt
->lastf2
->datalen
);
11633 if (handle_remote_phone_dtmf(myrpt
,f
->subclass
,&keyed
,phone_mode
) == -1)
11635 if (debug
) printf("@@@@ rpt:Hung Up\n");
11640 if (f
->frametype
== AST_FRAME_TEXT
)
11642 if (handle_remote_data(myrpt
,f
->data
) == -1)
11644 if (debug
) printf("@@@@ rpt:Hung Up\n");
11649 if (f
->frametype
== AST_FRAME_CONTROL
)
11651 if (f
->subclass
== AST_CONTROL_HANGUP
)
11653 if (debug
) printf("@@@@ rpt:Hung Up\n");
11658 if (f
->subclass
== AST_CONTROL_RADIO_KEY
)
11660 if (debug
== 7) printf("@@@@ rx key\n");
11662 myrpt
->rerxtimer
= 0;
11665 if (f
->subclass
== AST_CONTROL_RADIO_UNKEY
)
11667 myrpt
->rerxtimer
= 0;
11668 if (debug
== 7) printf("@@@@ rx un-key\n");
11675 if (who
== myrpt
->rxchannel
) /* if it was a read from radio */
11677 f
= ast_read(myrpt
->rxchannel
);
11680 if (debug
) printf("@@@@ link:Hung Up\n");
11683 if (f
->frametype
== AST_FRAME_VOICE
)
11687 if(!strcmp(myrpt
->remote
, remote_rig_kenwood
))
11690 if (myreming
|| (!remkeyed
) ||
11691 ((myrpt
->remote
) && (myrpt
->remotetx
)) ||
11692 ((myrpt
->remmode
!= REM_MODE_FM
) &&
11694 memset(f
->data
,0,f
->datalen
);
11695 ast_write(myrpt
->pchannel
,f
);
11697 else if (f
->frametype
== AST_FRAME_CONTROL
)
11699 if (f
->subclass
== AST_CONTROL_HANGUP
)
11701 if (debug
) printf("@@@@ rpt:Hung Up\n");
11706 if (f
->subclass
== AST_CONTROL_RADIO_KEY
)
11708 if (debug
== 7) printf("@@@@ remote rx key\n");
11709 if (!myrpt
->remotetx
)
11715 if (f
->subclass
== AST_CONTROL_RADIO_UNKEY
)
11717 if (debug
== 7) printf("@@@@ remote rx un-key\n");
11718 if (!myrpt
->remotetx
)
11727 if (who
== myrpt
->pchannel
) /* if is remote mix output */
11729 f
= ast_read(myrpt
->pchannel
);
11732 if (debug
) printf("@@@@ link:Hung Up\n");
11735 if (f
->frametype
== AST_FRAME_VOICE
)
11739 if (f
->frametype
== AST_FRAME_CONTROL
)
11741 if (f
->subclass
== AST_CONTROL_HANGUP
)
11743 if (debug
) printf("@@@@ rpt:Hung Up\n");
11751 if ((myrpt
->rxchannel
!= myrpt
->txchannel
) &&
11752 (who
== myrpt
->txchannel
)) /* do this cuz you have to */
11754 f
= ast_read(myrpt
->txchannel
);
11757 if (debug
) printf("@@@@ link:Hung Up\n");
11760 if (f
->frametype
== AST_FRAME_CONTROL
)
11762 if (f
->subclass
== AST_CONTROL_HANGUP
)
11764 if (debug
) printf("@@@@ rpt:Hung Up\n");
11773 if (myrpt
->p
.archivedir
)
11775 char mycmd
[100],*b
,*b1
;
11777 /* look at callerid to see what node this comes from */
11778 if (!chan
->cid
.cid_num
) /* if doesn't have caller id */
11782 ast_callerid_parse(chan
->cid
.cid_num
,&b
,&b1
);
11783 ast_shrink_phone_number(b1
);
11785 sprintf(mycmd
,"DISCONNECT,%s",b1
);
11786 donodelog(myrpt
,mycmd
);
11788 /* wait for telem to be done */
11789 while(myrpt
->tele
.next
!= &myrpt
->tele
) usleep(100000);
11790 sprintf(tmp
,"mixmonitor stop %s",chan
->name
);
11791 ast_cli_command(nullfd
,tmp
);
11793 rpt_mutex_lock(&myrpt
->lock
);
11794 myrpt
->hfscanmode
= 0;
11795 myrpt
->hfscanstatus
= 0;
11796 myrpt
->remoteon
= 0;
11797 rpt_mutex_unlock(&myrpt
->lock
);
11798 if (myrpt
->lastf1
) ast_frfree(myrpt
->lastf1
);
11799 myrpt
->lastf1
= NULL
;
11800 if (myrpt
->lastf2
) ast_frfree(myrpt
->lastf2
);
11801 myrpt
->lastf2
= NULL
;
11802 if ((iskenwood_pci4
) && (myrpt
->txchannel
== myrpt
->zaptxchannel
))
11804 z
.radpar
= ZT_RADPAR_UIOMODE
;
11806 if (ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&z
) == -1)
11808 ast_log(LOG_ERROR
,"Cannot set UIOMODE\n");
11811 z
.radpar
= ZT_RADPAR_UIODATA
;
11813 if (ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&z
) == -1)
11815 ast_log(LOG_ERROR
,"Cannot set UIODATA\n");
11819 if (ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_HOOK
,&i
) == -1)
11821 ast_log(LOG_ERROR
,"Cannot set hook\n");
11825 if (myrpt
->iofd
) close(myrpt
->iofd
);
11827 ast_hangup(myrpt
->pchannel
);
11828 if (myrpt
->rxchannel
!= myrpt
->txchannel
) ast_hangup(myrpt
->txchannel
);
11829 ast_hangup(myrpt
->rxchannel
);
11831 #ifdef OLD_ASTERISK
11832 LOCAL_USER_REMOVE(u
);
11837 #ifdef OLD_ASTERISK
11838 int unload_module()
11840 static int unload_module(void)
11845 #ifdef OLD_ASTERISK
11846 STANDARD_HANGUP_LOCALUSERS
;
11848 for(i
= 0; i
< nrpts
; i
++) {
11849 if (!strcmp(rpt_vars
[i
].name
,rpt_vars
[i
].p
.nodes
)) continue;
11850 ast_mutex_destroy(&rpt_vars
[i
].lock
);
11851 ast_mutex_destroy(&rpt_vars
[i
].remlock
);
11853 i
= ast_unregister_application(app
);
11855 /* Unregister cli extensions */
11856 ast_cli_unregister(&cli_debug
);
11857 ast_cli_unregister(&cli_dump
);
11858 ast_cli_unregister(&cli_stats
);
11859 ast_cli_unregister(&cli_lstats
);
11860 ast_cli_unregister(&cli_nodes
);
11861 ast_cli_unregister(&cli_reload
);
11862 ast_cli_unregister(&cli_restart
);
11863 ast_cli_unregister(&cli_fun
);
11868 #ifdef OLD_ASTERISK
11871 static int load_module(void)
11874 ast_pthread_create(&rpt_master_thread
,NULL
,rpt_master
,NULL
);
11876 /* Register cli extensions */
11877 ast_cli_register(&cli_debug
);
11878 ast_cli_register(&cli_dump
);
11879 ast_cli_register(&cli_stats
);
11880 ast_cli_register(&cli_lstats
);
11881 ast_cli_register(&cli_nodes
);
11882 ast_cli_register(&cli_reload
);
11883 ast_cli_register(&cli_restart
);
11884 ast_cli_register(&cli_fun
);
11886 return ast_register_application(app
, rpt_exec
, synopsis
, descrip
);
11889 #ifdef OLD_ASTERISK
11890 char *description()
11897 STANDARD_USECOUNT(res
);
11903 return ASTERISK_GPL_KEY
;
11907 #ifdef OLD_ASTERISK
11910 static int reload(void)
11915 for(n
= 0; n
< nrpts
; n
++) rpt_vars
[n
].reload
= 1;
11919 #ifndef OLD_ASTERISK
11920 /* STD_MOD(MOD_1, reload, NULL, NULL); */
11921 AST_MODULE_INFO(ASTERISK_GPL_KEY
, AST_MODFLAG_DEFAULT
, "Radio Repeater/Remote Base Application",
11922 .load
= load_module
,
11923 .unload
= unload_module
,