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
));
1650 int savearea
= (char *)&rpt_vars
[n
].p
- (char *)&rpt_vars
[n
];
1652 cp
= (char *) &rpt_vars
[n
].p
;
1653 memset(cp
+ sizeof(rpt_vars
[n
].p
),0,
1654 sizeof(rpt_vars
[n
]) - (sizeof(rpt_vars
[n
].p
) + savearea
));
1655 rpt_vars
[n
].tele
.next
= &rpt_vars
[n
].tele
;
1656 rpt_vars
[n
].tele
.prev
= &rpt_vars
[n
].tele
;
1657 rpt_vars
[n
].rpt_thread
= AST_PTHREADT_NULL
;
1658 rpt_vars
[n
].tailmessagen
= 0;
1661 /* zot out filters stuff */
1662 memset(&rpt_vars
[n
].filters
,0,sizeof(rpt_vars
[n
].filters
));
1664 val
= (char *) ast_variable_retrieve(cfg
,this,"context");
1665 if (val
) rpt_vars
[n
].p
.ourcontext
= val
;
1666 else rpt_vars
[n
].p
.ourcontext
= this;
1667 val
= (char *) ast_variable_retrieve(cfg
,this,"callerid");
1668 if (val
) rpt_vars
[n
].p
.ourcallerid
= val
;
1669 val
= (char *) ast_variable_retrieve(cfg
,this,"accountcode");
1670 if (val
) rpt_vars
[n
].p
.acctcode
= val
;
1671 val
= (char *) ast_variable_retrieve(cfg
,this,"idrecording");
1672 if (val
) rpt_vars
[n
].p
.ident
= val
;
1673 val
= (char *) ast_variable_retrieve(cfg
,this,"hangtime");
1674 if (val
) rpt_vars
[n
].p
.hangtime
= atoi(val
);
1675 else rpt_vars
[n
].p
.hangtime
= HANGTIME
;
1676 val
= (char *) ast_variable_retrieve(cfg
,this,"althangtime");
1677 if (val
) rpt_vars
[n
].p
.althangtime
= atoi(val
);
1678 else rpt_vars
[n
].p
.althangtime
= HANGTIME
;
1679 val
= (char *) ast_variable_retrieve(cfg
,this,"totime");
1680 if (val
) rpt_vars
[n
].p
.totime
= atoi(val
);
1681 else rpt_vars
[n
].p
.totime
= TOTIME
;
1682 rpt_vars
[n
].p
.tailmessagetime
= retrieve_astcfgint(&rpt_vars
[n
],this, "tailmessagetime", 0, 2400000, 0);
1683 rpt_vars
[n
].p
.tailsquashedtime
= retrieve_astcfgint(&rpt_vars
[n
],this, "tailsquashedtime", 0, 2400000, 0);
1684 rpt_vars
[n
].p
.duplex
= retrieve_astcfgint(&rpt_vars
[n
],this,"duplex",0,4,2);
1685 rpt_vars
[n
].p
.idtime
= retrieve_astcfgint(&rpt_vars
[n
],this, "idtime", -60000, 2400000, IDTIME
); /* Enforce a min max including zero */
1686 rpt_vars
[n
].p
.politeid
= retrieve_astcfgint(&rpt_vars
[n
],this, "politeid", 30000, 300000, POLITEID
); /* Enforce a min max */
1687 val
= (char *) ast_variable_retrieve(cfg
,this,"tonezone");
1688 if (val
) rpt_vars
[n
].p
.tonezone
= val
;
1689 rpt_vars
[n
].p
.tailmessages
[0] = 0;
1690 rpt_vars
[n
].p
.tailmessagemax
= 0;
1691 val
= (char *) ast_variable_retrieve(cfg
,this,"tailmessagelist");
1692 if (val
) rpt_vars
[n
].p
.tailmessagemax
= finddelim(val
, rpt_vars
[n
].p
.tailmessages
, 500);
1693 val
= (char *) ast_variable_retrieve(cfg
,this,"memory");
1694 if (!val
) val
= MEMORY
;
1695 rpt_vars
[n
].p
.memory
= val
;
1696 val
= (char *) ast_variable_retrieve(cfg
,this,"macro");
1697 if (!val
) val
= MACRO
;
1698 rpt_vars
[n
].p
.macro
= val
;
1699 val
= (char *) ast_variable_retrieve(cfg
,this,"startup_macro");
1700 if (val
) rpt_vars
[n
].p
.startupmacro
= val
;
1701 val
= (char *) ast_variable_retrieve(cfg
,this,"iobase");
1702 /* do not use atoi() here, we need to be able to have
1703 the input specified in hex or decimal so we use
1705 if ((!val
) || (sscanf(val
,"%i",&rpt_vars
[n
].p
.iobase
) != 1))
1706 rpt_vars
[n
].p
.iobase
= DEFAULT_IOBASE
;
1707 val
= (char *) ast_variable_retrieve(cfg
,this,"ioport");
1708 rpt_vars
[n
].p
.ioport
= val
;
1709 val
= (char *) ast_variable_retrieve(cfg
,this,"functions");
1713 rpt_vars
[n
].p
.simple
= 1;
1715 rpt_vars
[n
].p
.functions
= val
;
1716 val
= (char *) ast_variable_retrieve(cfg
,this,"link_functions");
1717 if (val
) rpt_vars
[n
].p
.link_functions
= val
;
1719 rpt_vars
[n
].p
.link_functions
= rpt_vars
[n
].p
.functions
;
1720 val
= (char *) ast_variable_retrieve(cfg
,this,"phone_functions");
1721 if (val
) rpt_vars
[n
].p
.phone_functions
= val
;
1722 val
= (char *) ast_variable_retrieve(cfg
,this,"dphone_functions");
1723 if (val
) rpt_vars
[n
].p
.dphone_functions
= val
;
1724 val
= (char *) ast_variable_retrieve(cfg
,this,"funcchar");
1725 if (!val
) rpt_vars
[n
].p
.funcchar
= FUNCCHAR
; else
1726 rpt_vars
[n
].p
.funcchar
= *val
;
1727 val
= (char *) ast_variable_retrieve(cfg
,this,"endchar");
1728 if (!val
) rpt_vars
[n
].p
.endchar
= ENDCHAR
; else
1729 rpt_vars
[n
].p
.endchar
= *val
;
1730 val
= (char *) ast_variable_retrieve(cfg
,this,"nobusyout");
1731 if (val
) rpt_vars
[n
].p
.nobusyout
= ast_true(val
);
1732 val
= (char *) ast_variable_retrieve(cfg
,this,"notelemtx");
1733 if (val
) rpt_vars
[n
].p
.notelemtx
= ast_true(val
);
1734 val
= (char *) ast_variable_retrieve(cfg
,this,"propagate_dtmf");
1735 if (val
) rpt_vars
[n
].p
.propagate_dtmf
= ast_true(val
);
1736 val
= (char *) ast_variable_retrieve(cfg
,this,"propagate_phonedtmf");
1737 if (val
) rpt_vars
[n
].p
.propagate_phonedtmf
= ast_true(val
);
1738 val
= (char *) ast_variable_retrieve(cfg
,this,"linktolink");
1739 if (val
) rpt_vars
[n
].p
.linktolink
= ast_true(val
);
1740 val
= (char *) ast_variable_retrieve(cfg
,this,"nodes");
1741 if (!val
) val
= NODES
;
1742 rpt_vars
[n
].p
.nodes
= val
;
1743 val
= (char *) ast_variable_retrieve(cfg
,this,"extnodes");
1744 if (!val
) val
= EXTNODES
;
1745 rpt_vars
[n
].p
.extnodes
= val
;
1746 val
= (char *) ast_variable_retrieve(cfg
,this,"extnodefile");
1747 if (!val
) val
= EXTNODEFILE
;
1748 rpt_vars
[n
].p
.extnodefile
= val
;
1749 val
= (char *) ast_variable_retrieve(cfg
,this,"archivedir");
1750 if (val
) rpt_vars
[n
].p
.archivedir
= val
;
1751 val
= (char *) ast_variable_retrieve(cfg
,this,"authlevel");
1752 if (val
) rpt_vars
[n
].p
.authlevel
= atoi(val
);
1753 else rpt_vars
[n
].p
.authlevel
= 0;
1754 val
= (char *) ast_variable_retrieve(cfg
,this,"monminblocks");
1755 if (val
) rpt_vars
[n
].p
.monminblocks
= atol(val
);
1756 else rpt_vars
[n
].p
.monminblocks
= DEFAULT_MONITOR_MIN_DISK_BLOCKS
;
1757 val
= (char *) ast_variable_retrieve(cfg
,this,"remote_inact_timeout");
1758 if (val
) rpt_vars
[n
].p
.remoteinacttimeout
= atoi(val
);
1759 else rpt_vars
[n
].p
.remoteinacttimeout
= DEFAULT_REMOTE_INACT_TIMEOUT
;
1760 val
= (char *) ast_variable_retrieve(cfg
,this,"civaddr");
1761 if (val
) rpt_vars
[n
].p
.civaddr
= atoi(val
);
1762 else rpt_vars
[n
].p
.civaddr
= DEFAULT_CIV_ADDR
;
1763 val
= (char *) ast_variable_retrieve(cfg
,this,"remote_timeout");
1764 if (val
) rpt_vars
[n
].p
.remotetimeout
= atoi(val
);
1765 else rpt_vars
[n
].p
.remotetimeout
= DEFAULT_REMOTE_TIMEOUT
;
1766 val
= (char *) ast_variable_retrieve(cfg
,this,"remote_timeout_warning");
1767 if (val
) rpt_vars
[n
].p
.remotetimeoutwarning
= atoi(val
);
1768 else rpt_vars
[n
].p
.remotetimeoutwarning
= DEFAULT_REMOTE_TIMEOUT_WARNING
;
1769 val
= (char *) ast_variable_retrieve(cfg
,this,"remote_timeout_warning_freq");
1770 if (val
) rpt_vars
[n
].p
.remotetimeoutwarningfreq
= atoi(val
);
1771 else rpt_vars
[n
].p
.remotetimeoutwarningfreq
= DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ
;
1773 val
= (char *) ast_variable_retrieve(cfg
,this,"rxnotch");
1775 i
= finddelim(val
,strs
,MAXFILTERS
* 2);
1776 i
&= ~1; /* force an even number, rounded down */
1777 if (i
>= 2) for(j
= 0; j
< i
; j
+= 2)
1779 rpt_mknotch(atof(strs
[j
]),atof(strs
[j
+ 1]),
1780 &rpt_vars
[n
].filters
[j
>> 1].gain
,
1781 &rpt_vars
[n
].filters
[j
>> 1].const0
,
1782 &rpt_vars
[n
].filters
[j
>> 1].const1
,
1783 &rpt_vars
[n
].filters
[j
>> 1].const2
);
1784 sprintf(rpt_vars
[n
].filters
[j
>> 1].desc
,"%s Hz, BW = %s",
1785 strs
[j
],strs
[j
+ 1]);
1790 val
= (char *) ast_variable_retrieve(cfg
,this,"inxlat");
1792 memset(&rpt_vars
[n
].p
.inxlat
,0,sizeof(struct rpt_xlat
));
1793 i
= finddelim(val
,strs
,3);
1794 if (i
) strncpy(rpt_vars
[n
].p
.inxlat
.funccharseq
,strs
[0],MAXXLAT
- 1);
1795 if (i
> 1) strncpy(rpt_vars
[n
].p
.inxlat
.endcharseq
,strs
[1],MAXXLAT
- 1);
1796 if (i
> 2) strncpy(rpt_vars
[n
].p
.inxlat
.passchars
,strs
[2],MAXXLAT
- 1);
1798 val
= (char *) ast_variable_retrieve(cfg
,this,"outxlat");
1800 memset(&rpt_vars
[n
].p
.outxlat
,0,sizeof(struct rpt_xlat
));
1801 i
= finddelim(val
,strs
,3);
1802 if (i
) strncpy(rpt_vars
[n
].p
.outxlat
.funccharseq
,strs
[0],MAXXLAT
- 1);
1803 if (i
> 1) strncpy(rpt_vars
[n
].p
.outxlat
.endcharseq
,strs
[1],MAXXLAT
- 1);
1804 if (i
> 2) strncpy(rpt_vars
[n
].p
.outxlat
.passchars
,strs
[2],MAXXLAT
- 1);
1806 /* retreive the stanza name for the control states if there is one */
1807 val
= (char *) ast_variable_retrieve(cfg
,this,"controlstates");
1808 rpt_vars
[n
].p
.csstanzaname
= val
;
1810 /* retreive the stanza name for the scheduler if there is one */
1811 val
= (char *) ast_variable_retrieve(cfg
,this,"scheduler");
1812 rpt_vars
[n
].p
.skedstanzaname
= val
;
1814 /* retreive the stanza name for the txlimits */
1815 val
= (char *) ast_variable_retrieve(cfg
,this,"txlimits");
1816 rpt_vars
[n
].p
.txlimitsstanzaname
= val
;
1820 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.nodes
);
1823 j
= strlen(vp
->name
);
1824 if (j
> longestnode
)
1829 rpt_vars
[n
].longestnode
= longestnode
;
1832 * For this repeater, Determine the length of the longest function
1834 rpt_vars
[n
].longestfunc
= 0;
1835 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.functions
);
1837 j
= strlen(vp
->name
);
1838 if (j
> rpt_vars
[n
].longestfunc
)
1839 rpt_vars
[n
].longestfunc
= j
;
1843 * For this repeater, Determine the length of the longest function
1845 rpt_vars
[n
].link_longestfunc
= 0;
1846 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.link_functions
);
1848 j
= strlen(vp
->name
);
1849 if (j
> rpt_vars
[n
].link_longestfunc
)
1850 rpt_vars
[n
].link_longestfunc
= j
;
1853 rpt_vars
[n
].phone_longestfunc
= 0;
1854 if (rpt_vars
[n
].p
.phone_functions
)
1856 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.phone_functions
);
1858 j
= strlen(vp
->name
);
1859 if (j
> rpt_vars
[n
].phone_longestfunc
)
1860 rpt_vars
[n
].phone_longestfunc
= j
;
1864 rpt_vars
[n
].dphone_longestfunc
= 0;
1865 if (rpt_vars
[n
].p
.dphone_functions
)
1867 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.dphone_functions
);
1869 j
= strlen(vp
->name
);
1870 if (j
> rpt_vars
[n
].dphone_longestfunc
)
1871 rpt_vars
[n
].dphone_longestfunc
= j
;
1875 rpt_vars
[n
].macro_longest
= 1;
1876 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.macro
);
1878 j
= strlen(vp
->name
);
1879 if (j
> rpt_vars
[n
].macro_longest
)
1880 rpt_vars
[n
].macro_longest
= j
;
1884 /* Browse for control states */
1885 if(rpt_vars
[n
].p
.csstanzaname
)
1886 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.csstanzaname
);
1889 for( i
= 0 ; vp
&& (i
< MAX_SYSSTATES
) ; i
++){ /* Iterate over the number of control state lines in the stanza */
1890 int k
,nukw
,statenum
;
1891 statenum
=atoi(vp
->name
);
1892 strncpy(s1
, vp
->value
, 255);
1894 nukw
= finddelim(s1
,strs
,32);
1896 for (k
= 0 ; k
< nukw
; k
++){ /* for each user specified keyword */
1897 for(j
= 0 ; cs_keywords
[j
] != NULL
; j
++){ /* try to match to one in our internal table */
1898 if(!strcmp(strs
[k
],cs_keywords
[j
])){
1900 case 0: /* rptena */
1901 rpt_vars
[n
].p
.s
[statenum
].txdisable
= 0;
1903 case 1: /* rptdis */
1904 rpt_vars
[n
].p
.s
[statenum
].txdisable
= 1;
1908 rpt_vars
[n
].p
.s
[statenum
].autopatchdisable
= 0;
1912 rpt_vars
[n
].p
.s
[statenum
].autopatchdisable
= 1;
1915 case 4: /* lnkena */
1916 rpt_vars
[n
].p
.s
[statenum
].linkfundisable
= 0;
1919 case 5: /* lnkdis */
1920 rpt_vars
[n
].p
.s
[statenum
].linkfundisable
= 1;
1923 case 6: /* totena */
1924 rpt_vars
[n
].p
.s
[statenum
].totdisable
= 0;
1927 case 7: /* totdis */
1928 rpt_vars
[n
].p
.s
[statenum
].totdisable
= 1;
1932 rpt_vars
[n
].p
.s
[statenum
].schedulerdisable
= 0;
1936 rpt_vars
[n
].p
.s
[statenum
].schedulerdisable
= 1;
1939 case 10: /* ufena */
1940 rpt_vars
[n
].p
.s
[statenum
].userfundisable
= 0;
1943 case 11: /* ufdis */
1944 rpt_vars
[n
].p
.s
[statenum
].userfundisable
= 1;
1947 case 12: /* atena */
1948 rpt_vars
[n
].p
.s
[statenum
].alternatetail
= 1;
1951 case 13: /* atdis */
1952 rpt_vars
[n
].p
.s
[statenum
].alternatetail
= 0;
1956 ast_log(LOG_WARNING
,
1957 "Unhandled control state keyword %s", cs_keywords
[i
]);
1965 ast_mutex_unlock(&rpt_vars
[n
].lock
);
1969 * Enable or disable debug output at a given level at the console
1972 static int rpt_do_debug(int fd
, int argc
, char *argv
[])
1977 return RESULT_SHOWUSAGE
;
1978 newlevel
= myatoi(argv
[3]);
1979 if((newlevel
< 0) || (newlevel
> 7))
1980 return RESULT_SHOWUSAGE
;
1982 ast_cli(fd
, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug
, newlevel
);
1984 ast_cli(fd
, "app_rpt Debugging disabled\n");
1987 return RESULT_SUCCESS
;
1991 * Dump rpt struct debugging onto console
1994 static int rpt_do_dump(int fd
, int argc
, char *argv
[])
1999 return RESULT_SHOWUSAGE
;
2001 for(i
= 0; i
< nrpts
; i
++)
2003 if (!strcmp(argv
[2],rpt_vars
[i
].name
))
2005 rpt_vars
[i
].disgorgetime
= time(NULL
) + 10; /* Do it 10 seconds later */
2006 ast_cli(fd
, "app_rpt struct dump requested for node %s\n",argv
[2]);
2007 return RESULT_SUCCESS
;
2010 return RESULT_FAILURE
;
2014 * Dump statistics onto console
2017 static int rpt_do_stats(int fd
, int argc
, char *argv
[])
2020 int dailytxtime
, dailykerchunks
;
2021 int totalkerchunks
, dailykeyups
, totalkeyups
, timeouts
;
2022 int totalexecdcommands
, dailyexecdcommands
, hours
, minutes
, seconds
;
2023 long long totaltxtime
;
2025 char *listoflinks
[MAX_STAT_LINKS
];
2026 char *lastnodewhichkeyedusup
, *lastdtmfcommand
;
2027 char *tot_state
, *ider_state
, *patch_state
;
2028 char *reverse_patch_state
, *sys_ena
, *tot_ena
, *link_ena
, *patch_ena
;
2029 char *sch_ena
, *input_signal
, *called_number
, *user_funs
, *tail_type
;
2032 static char *not_applicable
= "N/A";
2035 return RESULT_SHOWUSAGE
;
2037 for(i
= 0 ; i
< MAX_STAT_LINKS
; i
++)
2038 listoflinks
[i
] = NULL
;
2040 tot_state
= ider_state
=
2041 patch_state
= reverse_patch_state
=
2042 input_signal
= called_number
=
2043 lastdtmfcommand
= not_applicable
;
2045 for(i
= 0; i
< nrpts
; i
++)
2047 if (!strcmp(argv
[2],rpt_vars
[i
].name
)){
2048 /* Make a copy of all stat variables while locked */
2049 myrpt
= &rpt_vars
[i
];
2050 rpt_mutex_lock(&myrpt
->lock
); /* LOCK */
2052 dailytxtime
= myrpt
->dailytxtime
;
2053 totaltxtime
= myrpt
->totaltxtime
;
2054 dailykeyups
= myrpt
->dailykeyups
;
2055 totalkeyups
= myrpt
->totalkeyups
;
2056 dailykerchunks
= myrpt
->dailykerchunks
;
2057 totalkerchunks
= myrpt
->totalkerchunks
;
2058 dailyexecdcommands
= myrpt
->dailyexecdcommands
;
2059 totalexecdcommands
= myrpt
->totalexecdcommands
;
2060 timeouts
= myrpt
->timeouts
;
2062 /* Traverse the list of connected nodes */
2063 reverse_patch_state
= "DOWN";
2065 l
= myrpt
->links
.next
;
2066 while(l
&& (l
!= &myrpt
->links
)){
2067 if (l
->name
[0] == '0'){ /* Skip '0' nodes */
2068 reverse_patch_state
= "UP";
2072 listoflinks
[j
] = ast_strdupa(l
->name
);
2078 lastnodewhichkeyedusup
= ast_strdupa(myrpt
->lastnodewhichkeyedusup
);
2079 if((!lastnodewhichkeyedusup
) || (!strlen(lastnodewhichkeyedusup
)))
2080 lastnodewhichkeyedusup
= not_applicable
;
2083 input_signal
= "YES";
2085 input_signal
= "NO";
2087 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
)
2088 sys_ena
= "DISABLED";
2090 sys_ena
= "ENABLED";
2092 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].totdisable
)
2093 tot_ena
= "DISABLED";
2095 tot_ena
= "ENABLED";
2097 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].linkfundisable
)
2098 link_ena
= "DISABLED";
2100 link_ena
= "ENABLED";
2102 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].autopatchdisable
)
2103 patch_ena
= "DISABLED";
2105 patch_ena
= "ENABLED";
2107 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].schedulerdisable
)
2108 sch_ena
= "DISABLED";
2110 sch_ena
= "ENABLED";
2112 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].userfundisable
)
2113 user_funs
= "DISABLED";
2115 user_funs
= "ENABLED";
2117 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].alternatetail
)
2118 tail_type
= "ALTERNATE";
2120 tail_type
= "STANDARD";
2123 tot_state
= "TIMED OUT!";
2124 else if(myrpt
->totimer
!= myrpt
->p
.totime
)
2125 tot_state
= "ARMED";
2127 tot_state
= "RESET";
2130 ider_state
= "QUEUED IN TAIL";
2131 else if(myrpt
->mustid
)
2132 ider_state
= "QUEUED FOR CLEANUP";
2134 ider_state
= "CLEAN";
2136 switch(myrpt
->callmode
){
2138 patch_state
= "DIALING";
2141 patch_state
= "CONNECTING";
2148 patch_state
= "CALL FAILED";
2152 patch_state
= "DOWN";
2155 if(strlen(myrpt
->exten
)){
2156 called_number
= ast_strdupa(myrpt
->exten
);
2158 called_number
= not_applicable
;
2161 if(strlen(myrpt
->lastdtmfcommand
)){
2162 lastdtmfcommand
= ast_strdupa(myrpt
->lastdtmfcommand
);
2163 if(!lastdtmfcommand
)
2164 lastdtmfcommand
= not_applicable
;
2167 rpt_mutex_unlock(&myrpt
->lock
); /* UNLOCK */
2169 ast_cli(fd
, "************************ NODE %s STATISTICS *************************\n\n", myrpt
->name
);
2170 ast_cli(fd
, "Selected system state............................: %d\n", myrpt
->p
.sysstate_cur
);
2171 ast_cli(fd
, "Signal on input..................................: %s\n", input_signal
);
2172 ast_cli(fd
, "System...........................................: %s\n", sys_ena
);
2173 ast_cli(fd
, "Scheduler........................................: %s\n", sch_ena
);
2174 ast_cli(fd
, "Tail Time........................................: %s\n", tail_type
);
2175 ast_cli(fd
, "Time out timer...................................: %s\n", tot_ena
);
2176 ast_cli(fd
, "Time out timer state.............................: %s\n", tot_state
);
2177 ast_cli(fd
, "Time outs since system initialization............: %d\n", timeouts
);
2178 ast_cli(fd
, "Identifier state.................................: %s\n", ider_state
);
2179 ast_cli(fd
, "Kerchunks today..................................: %d\n", dailykerchunks
);
2180 ast_cli(fd
, "Kerchunks since system initialization............: %d\n", totalkerchunks
);
2181 ast_cli(fd
, "Keyups today.....................................: %d\n", dailykeyups
);
2182 ast_cli(fd
, "Keyups since system initialization...............: %d\n", totalkeyups
);
2183 ast_cli(fd
, "DTMF commands today..............................: %d\n", dailyexecdcommands
);
2184 ast_cli(fd
, "DTMF commands since system initialization........: %d\n", totalexecdcommands
);
2185 ast_cli(fd
, "Last DTMF command executed.......................: %s\n", lastdtmfcommand
);
2186 hours
= dailytxtime
/3600000;
2187 dailytxtime
%= 3600000;
2188 minutes
= dailytxtime
/60000;
2189 dailytxtime
%= 60000;
2190 seconds
= dailytxtime
/1000;
2191 dailytxtime
%= 1000;
2193 ast_cli(fd
, "TX time today ...................................: %02d:%02d:%02d.%d\n",
2194 hours
, minutes
, seconds
, dailytxtime
);
2196 hours
= (int) totaltxtime
/3600000;
2197 totaltxtime
%= 3600000;
2198 minutes
= (int) totaltxtime
/60000;
2199 totaltxtime
%= 60000;
2200 seconds
= (int) totaltxtime
/1000;
2201 totaltxtime
%= 1000;
2203 ast_cli(fd
, "TX time since system initialization..............: %02d:%02d:%02d.%d\n",
2204 hours
, minutes
, seconds
, (int) totaltxtime
);
2205 ast_cli(fd
, "Nodes currently connected to us..................: ");
2207 if(!listoflinks
[j
]){
2209 ast_cli(fd
,"<NONE>");
2213 ast_cli(fd
, "%s", listoflinks
[j
]);
2219 if(listoflinks
[j
+ 1])
2225 ast_cli(fd
, "Last node which transmitted to us................: %s\n", lastnodewhichkeyedusup
);
2226 ast_cli(fd
, "Autopatch........................................: %s\n", patch_ena
);
2227 ast_cli(fd
, "Autopatch state..................................: %s\n", patch_state
);
2228 ast_cli(fd
, "Autopatch called number..........................: %s\n", called_number
);
2229 ast_cli(fd
, "Reverse patch/IAXRPT connected...................: %s\n", reverse_patch_state
);
2230 ast_cli(fd
, "User linking commands............................: %s\n", link_ena
);
2231 ast_cli(fd
, "User functions...................................: %s\n\n", user_funs
);
2232 return RESULT_SUCCESS
;
2235 return RESULT_FAILURE
;
2239 * Link stats function
2242 static int rpt_do_lstats(int fd
, int argc
, char *argv
[])
2248 struct rpt_lstat
*s
,*t
;
2249 struct rpt_lstat s_head
;
2251 return RESULT_SHOWUSAGE
;
2254 s_head
.next
= &s_head
;
2255 s_head
.prev
= &s_head
;
2257 for(i
= 0; i
< nrpts
; i
++)
2259 if (!strcmp(argv
[2],rpt_vars
[i
].name
)){
2260 /* Make a copy of all stat variables while locked */
2261 myrpt
= &rpt_vars
[i
];
2262 rpt_mutex_lock(&myrpt
->lock
); /* LOCK */
2263 /* Traverse the list of connected nodes */
2265 l
= myrpt
->links
.next
;
2266 while(l
&& (l
!= &myrpt
->links
)){
2267 if (l
->name
[0] == '0'){ /* Skip '0' nodes */
2271 if((s
= (struct rpt_lstat
*) malloc(sizeof(struct rpt_lstat
))) == NULL
){
2272 ast_log(LOG_ERROR
, "Malloc failed in rpt_do_lstats\n");
2273 rpt_mutex_unlock(&myrpt
->lock
); /* UNLOCK */
2274 return RESULT_FAILURE
;
2276 memset(s
, 0, sizeof(struct rpt_lstat
));
2277 strncpy(s
->name
, l
->name
, MAXREMSTR
- 1);
2278 if (l
->chan
) pbx_substitute_variables_helper(l
->chan
, "${IAXPEER(CURRENTCHANNEL)}", s
->peer
, MAXPEERSTR
- 1);
2279 else strcpy(s
->peer
,"(none)");
2281 s
->outbound
= l
->outbound
;
2282 s
->reconnects
= l
->reconnects
;
2283 s
->connecttime
= l
->connecttime
;
2284 s
->thisconnected
= l
->thisconnected
;
2285 memcpy(s
->chan_stat
,l
->chan_stat
,NRPTSTAT
* sizeof(struct rpt_chan_stat
));
2286 insque((struct qelem
*) s
, (struct qelem
*) s_head
.next
);
2287 memset(l
->chan_stat
,0,NRPTSTAT
* sizeof(struct rpt_chan_stat
));
2290 rpt_mutex_unlock(&myrpt
->lock
); /* UNLOCK */
2291 ast_cli(fd
, "NODE PEER RECONNECTS DIRECTION CONNECT TIME CONNECT STATE\n");
2292 ast_cli(fd
, "---- ---- ---------- --------- ------------ -------------\n");
2294 for(s
= s_head
.next
; s
!= &s_head
; s
= s
->next
){
2295 int hours
, minutes
, seconds
;
2296 long long connecttime
= s
->connecttime
;
2298 hours
= (int) connecttime
/3600000;
2299 connecttime
%= 3600000;
2300 minutes
= (int) connecttime
/60000;
2301 connecttime
%= 60000;
2302 seconds
= (int) connecttime
/1000;
2303 connecttime
%= 1000;
2304 snprintf(conntime
, 20, "%02d:%02d:%02d.%d",
2305 hours
, minutes
, seconds
, (int) connecttime
);
2307 if(s
->thisconnected
)
2308 connstate
= "ESTABLISHED";
2310 connstate
= "CONNECTING";
2311 ast_cli(fd
, "%-10s%-20s%-12d%-11s%-20s%-20s\n",
2312 s
->name
, s
->peer
, s
->reconnects
, (s
->outbound
)? "OUT":"IN", conntime
, connstate
);
2314 /* destroy our local link queue */
2316 while(s
!= &s_head
){
2319 remque((struct qelem
*)t
);
2322 return RESULT_SUCCESS
;
2325 return RESULT_FAILURE
;
2329 * List all nodes connected, directly or indirectly
2332 static int rpt_do_nodes(int fd
, int argc
, char *argv
[])
2336 char lbuf
[MAXLINKLIST
],*strs
[MAXLINKLIST
];
2339 return RESULT_SHOWUSAGE
;
2341 for(i
= 0; i
< nrpts
; i
++)
2343 if (!strcmp(argv
[2],rpt_vars
[i
].name
)){
2344 /* Make a copy of all stat variables while locked */
2345 myrpt
= &rpt_vars
[i
];
2346 rpt_mutex_lock(&myrpt
->lock
); /* LOCK */
2347 __mklinklist(myrpt
,NULL
,lbuf
);
2348 rpt_mutex_unlock(&myrpt
->lock
); /* UNLOCK */
2350 ns
= finddelim(lbuf
,strs
,MAXLINKLIST
);
2352 if (ns
) qsort((void *)strs
,ns
,sizeof(char *),mycompar
);
2354 ast_cli(fd
, "************************* CONNECTED NODES *************************\n\n");
2358 ast_cli(fd
,"<NONE>");
2362 ast_cli(fd
, "%s", strs
[j
]);
2372 return RESULT_SUCCESS
;
2375 return RESULT_FAILURE
;
2382 static int rpt_do_reload(int fd
, int argc
, char *argv
[])
2386 if (argc
> 2) return RESULT_SHOWUSAGE
;
2388 for(n
= 0; n
< nrpts
; n
++) rpt_vars
[n
].reload
= 1;
2390 return RESULT_FAILURE
;
2397 static int rpt_do_restart(int fd
, int argc
, char *argv
[])
2401 if (argc
> 2) return RESULT_SHOWUSAGE
;
2402 for(i
= 0; i
< nrpts
; i
++)
2404 if (rpt_vars
[i
].rxchannel
) ast_softhangup(rpt_vars
[i
].rxchannel
,AST_SOFTHANGUP_DEV
);
2406 return RESULT_FAILURE
;
2411 * send an app_rpt DTMF function from the CLI
2414 static int rpt_do_fun(int fd
, int argc
, char *argv
[])
2418 if (argc
!= 4) return RESULT_SHOWUSAGE
;
2420 for(i
= 0; i
< nrpts
; i
++){
2421 if(!strcmp(argv
[2], rpt_vars
[i
].name
)){
2422 struct rpt
*myrpt
= &rpt_vars
[i
];
2423 rpt_mutex_lock(&myrpt
->lock
);
2424 if ((MAXMACRO
- strlen(myrpt
->macrobuf
)) < strlen(argv
[3])){
2425 rpt_mutex_unlock(&myrpt
->lock
);
2429 myrpt
->macrotimer
= MACROTIME
;
2430 strncat(myrpt
->macrobuf
,argv
[3],MAXMACRO
- 1);
2432 rpt_mutex_unlock(&myrpt
->lock
);
2436 ast_cli(fd
, "Function decoder busy");
2438 return RESULT_FAILURE
;
2443 static int play_tone_pair(struct ast_channel
*chan
, int f1
, int f2
, int duration
, int amplitude
)
2447 if ((res
= ast_tonepair_start(chan
, f1
, f2
, duration
, amplitude
)))
2450 while(chan
->generatordata
) {
2451 if (ast_safe_sleep(chan
,1)) return -1;
2457 static int play_tone(struct ast_channel
*chan
, int freq
, int duration
, int amplitude
)
2459 return play_tone_pair(chan
, freq
, 0, duration
, amplitude
);
2462 static int play_silence(struct ast_channel
*chan
, int duration
)
2464 return play_tone_pair(chan
, 0, 0, duration
, 0);
2468 static int send_morse(struct ast_channel
*chan
, char *string
, int speed
, int freq
, int amplitude
)
2471 static struct morse_bits mbits
[] = {
2536 int intralettertime
;
2537 int interlettertime
;
2547 /* Approximate the dot time from the speed arg. */
2549 dottime
= 900/speed
;
2551 /* Establish timing releationships */
2553 dashtime
= 3 * dottime
;
2554 intralettertime
= dottime
;
2555 interlettertime
= dottime
* 4 ;
2556 interwordtime
= dottime
* 7;
2558 for(;(*string
) && (!res
); string
++){
2562 /* Convert lower case to upper case */
2564 if((c
>= 'a') && (c
<= 'z'))
2567 /* Can't deal with any char code greater than Z, skip it */
2572 /* If space char, wait the inter word time */
2576 res
= play_silence(chan
, interwordtime
);
2580 /* Subtract out control char offset to match our table */
2584 /* Get the character data */
2587 ddcomb
= mbits
[c
].ddcomb
;
2589 /* Send the character */
2593 res
= play_tone(chan
, freq
, (ddcomb
& 1) ? dashtime
: dottime
, amplitude
);
2595 res
= play_silence(chan
, intralettertime
);
2599 /* Wait the interletter time */
2602 res
= play_silence(chan
, interlettertime
- intralettertime
);
2605 /* Wait for all the frames to be sent */
2608 res
= ast_waitstream(chan
, "");
2609 ast_stopstream(chan
);
2612 * Wait for the zaptel driver to physically write the tone blocks to the hardware
2615 for(i
= 0; i
< 20 ; i
++){
2616 flags
= ZT_IOMUX_WRITEEMPTY
| ZT_IOMUX_NOWAIT
;
2617 res
= ioctl(chan
->fds
[0], ZT_IOMUX
, &flags
);
2618 if(flags
& ZT_IOMUX_WRITEEMPTY
)
2620 if( ast_safe_sleep(chan
, 50)){
2630 static int send_tone_telemetry(struct ast_channel
*chan
, char *tonestring
)
2643 stringp
= ast_strdupa(tonestring
);
2646 tonesubset
= strsep(&stringp
,")");
2649 if(sscanf(tonesubset
,"(%d,%d,%d,%d", &f1
, &f2
, &duration
, &litude
) != 4)
2651 res
= play_tone_pair(chan
, f1
, f2
, duration
, amplitude
);
2656 res
= play_tone_pair(chan
, 0, 0, 100, 0); /* This is needed to ensure the last tone segment is timed correctly */
2659 res
= ast_waitstream(chan
, "");
2660 ast_stopstream(chan
);
2663 * Wait for the zaptel driver to physically write the tone blocks to the hardware
2666 for(i
= 0; i
< 20 ; i
++){
2667 flags
= ZT_IOMUX_WRITEEMPTY
| ZT_IOMUX_NOWAIT
;
2668 res
= ioctl(chan
->fds
[0], ZT_IOMUX
, &flags
);
2669 if(flags
& ZT_IOMUX_WRITEEMPTY
)
2671 if( ast_safe_sleep(chan
, 50)){
2681 static int sayfile(struct ast_channel
*mychannel
,char *fname
)
2685 res
= ast_streamfile(mychannel
, fname
, mychannel
->language
);
2687 res
= ast_waitstream(mychannel
, "");
2689 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
2690 ast_stopstream(mychannel
);
2694 static int saycharstr(struct ast_channel
*mychannel
,char *str
)
2698 res
= ast_say_character_str(mychannel
,str
,NULL
,mychannel
->language
);
2700 res
= ast_waitstream(mychannel
, "");
2702 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
2703 ast_stopstream(mychannel
);
2707 static int saynum(struct ast_channel
*mychannel
, int num
)
2710 res
= ast_say_number(mychannel
, num
, NULL
, mychannel
->language
, NULL
);
2712 res
= ast_waitstream(mychannel
, "");
2714 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
2715 ast_stopstream(mychannel
);
2720 static int telem_any(struct rpt
*myrpt
,struct ast_channel
*chan
, char *entry
)
2725 static int morsespeed
;
2726 static int morsefreq
;
2727 static int morseampl
;
2728 static int morseidfreq
= 0;
2729 static int morseidampl
;
2730 static char mcat
[] = MORSE
;
2734 if(!morseidfreq
){ /* Get the morse parameters if not already loaded */
2735 morsespeed
= retrieve_astcfgint(myrpt
, mcat
, "speed", 5, 20, 20);
2736 morsefreq
= retrieve_astcfgint(myrpt
, mcat
, "frequency", 300, 3000, 800);
2737 morseampl
= retrieve_astcfgint(myrpt
, mcat
, "amplitude", 200, 8192, 4096);
2738 morseidampl
= retrieve_astcfgint(myrpt
, mcat
, "idamplitude", 200, 8192, 2048);
2739 morseidfreq
= retrieve_astcfgint(myrpt
, mcat
, "idfrequency", 300, 3000, 330);
2742 /* Is it a file, or a tone sequence? */
2744 if(entry
[0] == '|'){
2746 if((c
>= 'a')&&(c
<= 'z'))
2750 case 'I': /* Morse ID */
2751 res
= send_morse(chan
, entry
+ 2, morsespeed
, morseidfreq
, morseidampl
);
2754 case 'M': /* Morse Message */
2755 res
= send_morse(chan
, entry
+ 2, morsespeed
, morsefreq
, morseampl
);
2758 case 'T': /* Tone sequence */
2759 res
= send_tone_telemetry(chan
, entry
+ 2);
2766 res
= sayfile(chan
, entry
); /* File */
2771 * This function looks up a telemetry name in the config file, and does a telemetry response as configured.
2773 * 4 types of telemtry are handled: Morse ID, Morse Message, Tone Sequence, and a File containing a recording.
2776 static int telem_lookup(struct rpt
*myrpt
,struct ast_channel
*chan
, char *node
, char *name
)
2783 char *telemetry_save
;
2786 telemetry_save
= NULL
;
2789 /* Retrieve the section name for telemetry from the node section */
2790 telemetry
= (char *) ast_variable_retrieve(myrpt
->cfg
, node
, TELEMETRY
);
2792 telemetry_save
= ast_strdupa(telemetry
);
2793 if(!telemetry_save
){
2794 ast_log(LOG_WARNING
,"ast_strdupa() failed in telem_lookup()\n");
2797 entry
= (char *) ast_variable_retrieve(myrpt
->cfg
, telemetry_save
, name
);
2800 /* Try to look up the telemetry name */
2803 /* Telemetry name wasn't found in the config file, use the default */
2804 for(i
= 0; i
< sizeof(tele_defs
)/sizeof(struct telem_defaults
) ; i
++){
2805 if(!strcasecmp(tele_defs
[i
].name
, name
))
2806 entry
= tele_defs
[i
].value
;
2811 telem_any(myrpt
,chan
, entry
);
2820 * Retrieve a wait interval
2823 static int get_wait_interval(struct rpt
*myrpt
, int type
)
2827 char *wait_times_save
;
2829 wait_times_save
= NULL
;
2830 wait_times
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->name
, "wait_times");
2833 wait_times_save
= ast_strdupa(wait_times
);
2834 if(!wait_times_save
){
2835 ast_log(LOG_WARNING
, "Out of memory in wait_interval()\n");
2843 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "telemwait", 500, 5000, 1000);
2850 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "idwait",250,5000,500);
2857 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "unkeywait",500,5000,1000);
2864 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "linkunkeywait",500,5000,1000);
2871 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "calltermwait",500,5000,1500);
2878 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "compwait",500,5000,200);
2891 * Wait a configurable interval of time
2895 static void wait_interval(struct rpt
*myrpt
, int type
, struct ast_channel
*chan
)
2898 interval
= get_wait_interval(myrpt
, type
);
2900 ast_log(LOG_NOTICE
," Delay interval = %d\n", interval
);
2902 ast_safe_sleep(chan
,interval
);
2904 ast_log(LOG_NOTICE
,"Delay complete\n");
2908 static int split_freq(char *mhz
, char *decimals
, char *freq
);
2910 static void *rpt_tele_thread(void *this)
2912 ZT_CONFINFO ci
; /* conference info */
2913 int res
= 0,haslink
,hastx
,hasremote
,imdone
= 0, unkeys_queued
, x
;
2914 struct rpt_tele
*mytele
= (struct rpt_tele
*)this;
2915 struct rpt_tele
*tlist
;
2917 struct rpt_link
*l
,*l1
,linkbase
;
2918 struct ast_channel
*mychannel
;
2919 int vmajor
, vminor
, m
;
2920 char *p
,*ct
,*ct_copy
,*ident
, *nodename
,*cp
;
2923 char lbuf
[MAXLINKLIST
],*strs
[MAXLINKLIST
];
2925 char mhz
[MAXREMSTR
];
2926 char decimals
[MAXREMSTR
];
2927 struct zt_params par
;
2930 /* get a pointer to myrpt */
2931 myrpt
= mytele
->rpt
;
2933 /* Snag copies of a few key myrpt variables */
2934 rpt_mutex_lock(&myrpt
->lock
);
2935 nodename
= ast_strdupa(myrpt
->name
);
2936 if (myrpt
->p
.ident
) ident
= ast_strdupa(myrpt
->p
.ident
);
2938 rpt_mutex_unlock(&myrpt
->lock
);
2940 /* allocate a pseudo-channel thru asterisk */
2941 mychannel
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
2944 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
2945 rpt_mutex_lock(&myrpt
->lock
);
2946 remque((struct qelem
*)mytele
);
2947 ast_log(LOG_NOTICE
,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__
, mytele
->mode
); /*@@@@@@@@@@@*/
2948 rpt_mutex_unlock(&myrpt
->lock
);
2952 #ifdef AST_CDR_FLAG_POST_DISABLED
2953 ast_set_flag(mychannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
2955 rpt_mutex_lock(&myrpt
->lock
);
2956 mytele
->chan
= mychannel
;
2957 rpt_mutex_unlock(&myrpt
->lock
);
2958 /* make a conference for the tx */
2960 /* If there's an ID queued, or tail message queued, */
2961 /* only connect the ID audio to the local tx conference so */
2962 /* linked systems can't hear it */
2963 ci
.confno
= (((mytele
->mode
== ID
) || (mytele
->mode
== IDTALKOVER
) || (mytele
->mode
== UNKEY
) ||
2964 (mytele
->mode
== TAILMSG
) || (mytele
->mode
== LINKUNKEY
)) || (mytele
->mode
== TIMEOUT
) ?
2965 myrpt
->txconf
: myrpt
->conf
);
2966 ci
.confmode
= ZT_CONF_CONFANN
;
2967 /* first put the channel on the conference in announce mode */
2968 if (ioctl(mychannel
->fds
[0],ZT_SETCONF
,&ci
) == -1)
2970 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
2971 rpt_mutex_lock(&myrpt
->lock
);
2972 remque((struct qelem
*)mytele
);
2973 rpt_mutex_unlock(&myrpt
->lock
);
2974 ast_log(LOG_NOTICE
,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__
, mytele
->mode
); /*@@@@@@@@@@@*/
2976 ast_hangup(mychannel
);
2979 ast_stopstream(mychannel
);
2980 switch(mytele
->mode
)
2985 wait_interval(myrpt
, (mytele
->mode
== ID
) ? DLY_ID
: DLY_TELEM
,mychannel
);
2986 res
= telem_any(myrpt
,mychannel
, ident
);
2991 res
= ast_streamfile(mychannel
, myrpt
->p
.tailmessages
[myrpt
->tailmessagen
], mychannel
->language
);
2995 p
= (char *) ast_variable_retrieve(myrpt
->cfg
, nodename
, "idtalkover");
2997 res
= telem_any(myrpt
,mychannel
, p
);
3002 /* wait a little bit longer */
3003 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3004 res
= telem_lookup(myrpt
, mychannel
, myrpt
->name
, "patchup");
3005 if(res
< 0){ /* Then default message */
3006 res
= ast_streamfile(mychannel
, "rpt/callproceeding", mychannel
->language
);
3010 /* wait a little bit longer */
3011 wait_interval(myrpt
, DLY_CALLTERM
, mychannel
);
3012 res
= telem_lookup(myrpt
, mychannel
, myrpt
->name
, "patchdown");
3013 if(res
< 0){ /* Then default message */
3014 res
= ast_streamfile(mychannel
, "rpt/callterminated", mychannel
->language
);
3018 /* wait a little bit */
3019 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3020 res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "functcomplete");
3022 case MACRO_NOTFOUND
:
3023 /* wait a little bit */
3024 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3025 res
= ast_streamfile(mychannel
, "rpt/macro_notfound", mychannel
->language
);
3028 /* wait a little bit */
3029 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3030 res
= ast_streamfile(mychannel
, "rpt/macro_busy", mychannel
->language
);
3033 if(myrpt
->patchnoct
&& myrpt
->callmode
){ /* If no CT during patch configured, then don't send one */
3039 * Reset the Unkey to CT timer
3042 x
= get_wait_interval(myrpt
, DLY_UNKEY
);
3043 rpt_mutex_lock(&myrpt
->lock
);
3044 myrpt
->unkeytocttimer
= x
; /* Must be protected as it is changed below */
3045 rpt_mutex_unlock(&myrpt
->lock
);
3048 * If there's one already queued, don't do another
3051 tlist
= myrpt
->tele
.next
;
3053 if (tlist
!= &myrpt
->tele
)
3055 rpt_mutex_lock(&myrpt
->lock
);
3056 while(tlist
!= &myrpt
->tele
){
3057 if (tlist
->mode
== UNKEY
) unkeys_queued
++;
3058 tlist
= tlist
->next
;
3060 rpt_mutex_unlock(&myrpt
->lock
);
3062 if( unkeys_queued
> 1){
3067 /* Wait for the telemetry timer to expire */
3068 /* Periodically check the timer since it can be re-initialized above */
3069 while(myrpt
->unkeytocttimer
)
3072 if(myrpt
->unkeytocttimer
> 100)
3075 ctint
= myrpt
->unkeytocttimer
;
3076 ast_safe_sleep(mychannel
, ctint
);
3077 rpt_mutex_lock(&myrpt
->lock
);
3078 if(myrpt
->unkeytocttimer
< ctint
)
3079 myrpt
->unkeytocttimer
= 0;
3081 myrpt
->unkeytocttimer
-= ctint
;
3082 rpt_mutex_unlock(&myrpt
->lock
);
3086 * Now, the carrier on the rptr rx should be gone.
3087 * If it re-appeared, then forget about sending the CT
3094 rpt_mutex_lock(&myrpt
->lock
); /* Update the kerchunk counters */
3095 myrpt
->dailykerchunks
++;
3096 myrpt
->totalkerchunks
++;
3097 rpt_mutex_unlock(&myrpt
->lock
);
3102 l
= myrpt
->links
.next
;
3103 if (l
!= &myrpt
->links
)
3105 rpt_mutex_lock(&myrpt
->lock
);
3106 while(l
!= &myrpt
->links
)
3108 if (l
->name
[0] == '0')
3116 if (l
->isremote
) hasremote
++;
3120 rpt_mutex_unlock(&myrpt
->lock
);
3125 res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, (!hastx
) ? "remotemon" : "remotetx");
3127 ast_log(LOG_WARNING
, "telem_lookup:remotexx failed on %s\n", mychannel
->name
);
3130 /* if in remote cmd mode, indicate it */
3131 if (myrpt
->cmdnode
[0])
3133 ast_safe_sleep(mychannel
,200);
3134 res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "cmdmode");
3136 ast_log(LOG_WARNING
, "telem_lookup:cmdmode failed on %s\n", mychannel
->name
);
3137 ast_stopstream(mychannel
);
3140 else if((ct
= (char *) ast_variable_retrieve(myrpt
->cfg
, nodename
, "unlinkedct"))){ /* Unlinked Courtesy Tone */
3141 ct_copy
= ast_strdupa(ct
);
3142 res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, ct_copy
);
3144 ast_log(LOG_WARNING
, "telem_lookup:ctx failed on %s\n", mychannel
->name
);
3146 if (hasremote
&& (!myrpt
->cmdnode
[0]))
3148 /* set for all to hear */
3150 ci
.confno
= myrpt
->conf
;
3151 ci
.confmode
= ZT_CONF_CONFANN
;
3152 /* first put the channel on the conference in announce mode */
3153 if (ioctl(mychannel
->fds
[0],ZT_SETCONF
,&ci
) == -1)
3155 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
3156 rpt_mutex_lock(&myrpt
->lock
);
3157 remque((struct qelem
*)mytele
);
3158 rpt_mutex_unlock(&myrpt
->lock
);
3159 ast_log(LOG_NOTICE
,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__
, mytele
->mode
); /*@@@@@@@@@@@*/
3161 ast_hangup(mychannel
);
3164 if((ct
= (char *) ast_variable_retrieve(myrpt
->cfg
, nodename
, "remotect"))){ /* Unlinked Courtesy Tone */
3165 ast_safe_sleep(mychannel
,200);
3166 ct_copy
= ast_strdupa(ct
);
3167 res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, ct_copy
);
3169 ast_log(LOG_WARNING
, "telem_lookup:ctx failed on %s\n", mychannel
->name
);
3172 #if defined(_MDC_DECODE_H_) && defined(MDC_SAY_WHEN_DOING_CT)
3173 if (myrpt
->lastunit
)
3177 ast_safe_sleep(mychannel
,200);
3178 /* set for all to hear */
3180 ci
.confno
= myrpt
->txconf
;
3181 ci
.confmode
= ZT_CONF_CONFANN
;
3182 /* first put the channel on the conference in announce mode */
3183 if (ioctl(mychannel
->fds
[0],ZT_SETCONF
,&ci
) == -1)
3185 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
3186 rpt_mutex_lock(&myrpt
->lock
);
3187 remque((struct qelem
*)mytele
);
3188 rpt_mutex_unlock(&myrpt
->lock
);
3189 ast_log(LOG_NOTICE
,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__
, mytele
->mode
); /*@@@@@@@@@@@*/
3191 ast_hangup(mychannel
);
3194 sprintf(mystr
,"%04x",myrpt
->lastunit
);
3195 myrpt
->lastunit
= 0;
3196 ast_say_character_str(mychannel
,mystr
,NULL
,mychannel
->language
);
3203 if(myrpt
->patchnoct
&& myrpt
->callmode
){ /* If no CT during patch configured, then don't send one */
3209 * Reset the Unkey to CT timer
3212 x
= get_wait_interval(myrpt
, DLY_LINKUNKEY
);
3213 mytele
->mylink
.linkunkeytocttimer
= x
; /* Must be protected as it is changed below */
3216 * If there's one already queued, don't do another
3219 tlist
= myrpt
->tele
.next
;
3221 if (tlist
!= &myrpt
->tele
)
3223 rpt_mutex_lock(&myrpt
->lock
);
3224 while(tlist
!= &myrpt
->tele
){
3225 if (tlist
->mode
== LINKUNKEY
) unkeys_queued
++;
3226 tlist
= tlist
->next
;
3228 rpt_mutex_unlock(&myrpt
->lock
);
3230 if( unkeys_queued
> 1){
3235 /* Wait for the telemetry timer to expire */
3236 /* Periodically check the timer since it can be re-initialized above */
3237 while(mytele
->mylink
.linkunkeytocttimer
)
3240 if(mytele
->mylink
.linkunkeytocttimer
> 100)
3243 ctint
= mytele
->mylink
.linkunkeytocttimer
;
3244 ast_safe_sleep(mychannel
, ctint
);
3245 rpt_mutex_lock(&myrpt
->lock
);
3246 if(mytele
->mylink
.linkunkeytocttimer
< ctint
)
3247 mytele
->mylink
.linkunkeytocttimer
= 0;
3249 mytele
->mylink
.linkunkeytocttimer
-= ctint
;
3250 rpt_mutex_unlock(&myrpt
->lock
);
3253 if((ct
= (char *) ast_variable_retrieve(myrpt
->cfg
, nodename
, "linkunkeyct"))){ /* Unlinked Courtesy Tone */
3254 ct_copy
= ast_strdupa(ct
);
3255 res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, ct_copy
);
3257 ast_log(LOG_WARNING
, "telem_lookup:ctx failed on %s\n", mychannel
->name
);
3262 /* wait a little bit */
3263 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3264 l
= myrpt
->links
.next
;
3266 /* dont report if a link for this one still on system */
3267 if (l
!= &myrpt
->links
)
3269 rpt_mutex_lock(&myrpt
->lock
);
3270 while(l
!= &myrpt
->links
)
3272 if (l
->name
[0] == '0')
3277 if (!strcmp(l
->name
,mytele
->mylink
.name
))
3284 rpt_mutex_unlock(&myrpt
->lock
);
3291 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3293 res
= ast_waitstream(mychannel
, "");
3295 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3296 ast_stopstream(mychannel
);
3297 ast_say_character_str(mychannel
,mytele
->mylink
.name
,NULL
,mychannel
->language
);
3298 res
= ast_streamfile(mychannel
, ((mytele
->mylink
.hasconnected
) ?
3299 "rpt/remote_disc" : "rpt/remote_busy"), mychannel
->language
);
3302 /* wait a little bit */
3303 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3304 res
= ast_streamfile(mychannel
, "rpt/remote_already", mychannel
->language
);
3307 /* wait a little bit */
3308 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3309 res
= ast_streamfile(mychannel
, "rpt/remote_notfound", mychannel
->language
);
3312 /* wait a little bit */
3313 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3314 res
= ast_streamfile(mychannel
, "rpt/remote_go", mychannel
->language
);
3317 /* wait a little bit */
3318 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3319 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3321 res
= ast_waitstream(mychannel
, "");
3323 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3324 ast_stopstream(mychannel
);
3325 ast_say_character_str(mychannel
,mytele
->mylink
.name
,NULL
,mychannel
->language
);
3326 res
= ast_streamfile(mychannel
, "rpt/connected", mychannel
->language
);
3328 res
= ast_waitstream(mychannel
, "");
3330 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3331 ast_stopstream(mychannel
);
3332 res
= ast_streamfile(mychannel
, "digits/2", mychannel
->language
);
3334 res
= ast_waitstream(mychannel
, "");
3336 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3337 ast_stopstream(mychannel
);
3338 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3340 res
= ast_waitstream(mychannel
, "");
3342 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3343 ast_stopstream(mychannel
);
3344 ast_say_character_str(mychannel
,myrpt
->name
,NULL
,mychannel
->language
);
3348 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3350 res
= ast_waitstream(mychannel
, "");
3352 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3353 ast_stopstream(mychannel
);
3354 ast_say_character_str(mychannel
,mytele
->mylink
.name
,NULL
,mychannel
->language
);
3355 res
= ast_streamfile(mychannel
, "rpt/connection_failed", mychannel
->language
);
3358 /* wait a little bit */
3359 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3360 res
= ast_streamfile(mychannel
, "rpt/memory_notfound", mychannel
->language
);
3363 ast_mutex_lock(&myrpt
->remlock
);
3365 if(!strcmp(myrpt
->remote
, remote_rig_ft897
))
3367 res
= set_ft897(myrpt
);
3369 if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
3371 res
= set_ic706(myrpt
);
3373 else if(!strcmp(myrpt
->remote
, remote_rig_rbi
))
3375 if (ioperm(myrpt
->p
.iobase
,1,1) == -1)
3377 rpt_mutex_unlock(&myrpt
->lock
);
3378 ast_log(LOG_WARNING
, "Cant get io permission on IO port %x hex\n",myrpt
->p
.iobase
);
3381 else res
= setrbi(myrpt
);
3383 else if(!strcmp(myrpt
->remote
, remote_rig_kenwood
))
3385 res
= setkenwood(myrpt
);
3386 if (ast_safe_sleep(mychannel
,200) == -1)
3388 ast_mutex_unlock(&myrpt
->remlock
);
3393 if (ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_FLUSH
,&i
) == -1)
3395 ast_mutex_unlock(&myrpt
->remlock
);
3396 ast_log(LOG_ERROR
,"Cant flush events");
3400 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_GET_PARAMS
,&par
) == -1)
3402 ast_mutex_unlock(&myrpt
->remlock
);
3403 ast_log(LOG_ERROR
,"Cant get params");
3408 (par
.rxisoffhook
|| (myrpt
->tele
.next
!= &myrpt
->tele
));
3410 ast_mutex_unlock(&myrpt
->remlock
);
3416 /* fall thru to invalid freq */
3418 /* wait a little bit */
3419 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3420 res
= ast_streamfile(mychannel
, "rpt/invalid-freq", mychannel
->language
);
3424 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3425 switch(myrpt
->remmode
)
3428 saycharstr(mychannel
,"FM");
3431 saycharstr(mychannel
,"USB");
3434 saycharstr(mychannel
,"LSB");
3437 saycharstr(mychannel
,"AM");
3440 wait_interval(myrpt
, DLY_COMP
, mychannel
);
3441 if (!res
) res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "functcomplete");
3444 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3445 sayfile(mychannel
,"rpt/login");
3446 saycharstr(mychannel
,myrpt
->name
);
3449 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3450 saycharstr(mychannel
,myrpt
->loginuser
);
3451 sayfile(mychannel
,"rpt/node");
3452 saycharstr(mychannel
,myrpt
->name
);
3453 wait_interval(myrpt
, DLY_COMP
, mychannel
);
3454 if (!res
) res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "functcomplete");
3457 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3459 switch(mytele
->submode
)
3461 case 100: /* RX PL Off */
3462 sayfile(mychannel
, "rpt/rxpl");
3463 sayfile(mychannel
, "rpt/off");
3465 case 101: /* RX PL On */
3466 sayfile(mychannel
, "rpt/rxpl");
3467 sayfile(mychannel
, "rpt/on");
3469 case 102: /* TX PL Off */
3470 sayfile(mychannel
, "rpt/txpl");
3471 sayfile(mychannel
, "rpt/off");
3473 case 103: /* TX PL On */
3474 sayfile(mychannel
, "rpt/txpl");
3475 sayfile(mychannel
, "rpt/on");
3477 case 104: /* Low Power */
3478 sayfile(mychannel
, "rpt/lopwr");
3480 case 105: /* Medium Power */
3481 sayfile(mychannel
, "rpt/medpwr");
3483 case 106: /* Hi Power */
3484 sayfile(mychannel
, "rpt/hipwr");
3486 case 113: /* Scan down slow */
3487 sayfile(mychannel
,"rpt/down");
3488 sayfile(mychannel
, "rpt/slow");
3490 case 114: /* Scan down quick */
3491 sayfile(mychannel
,"rpt/down");
3492 sayfile(mychannel
, "rpt/quick");
3494 case 115: /* Scan down fast */
3495 sayfile(mychannel
,"rpt/down");
3496 sayfile(mychannel
, "rpt/fast");
3498 case 116: /* Scan up slow */
3499 sayfile(mychannel
,"rpt/up");
3500 sayfile(mychannel
, "rpt/slow");
3502 case 117: /* Scan up quick */
3503 sayfile(mychannel
,"rpt/up");
3504 sayfile(mychannel
, "rpt/quick");
3506 case 118: /* Scan up fast */
3507 sayfile(mychannel
,"rpt/up");
3508 sayfile(mychannel
, "rpt/fast");
3513 wait_interval(myrpt
, DLY_COMP
, mychannel
);
3514 if (!res
) res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "functcomplete");
3517 ast_mutex_lock(&myrpt
->remlock
);
3518 if (myrpt
->hfscanstop
)
3520 myrpt
->hfscanstatus
= 0;
3521 myrpt
->hfscanmode
= 0;
3522 myrpt
->hfscanstop
= 0;
3523 mytele
->mode
= SCANSTAT
;
3524 ast_mutex_unlock(&myrpt
->remlock
);
3525 if (ast_safe_sleep(mychannel
,1000) == -1) break;
3526 sayfile(mychannel
, "rpt/stop");
3530 if (myrpt
->hfscanstatus
> -2) service_scan(myrpt
);
3531 i
= myrpt
->hfscanstatus
;
3532 myrpt
->hfscanstatus
= 0;
3533 if (i
) mytele
->mode
= SCANSTAT
;
3534 ast_mutex_unlock(&myrpt
->remlock
);
3535 if (i
< 0) sayfile(mychannel
, "rpt/stop");
3536 else if (i
> 0) saynum(mychannel
,i
);
3540 ast_mutex_lock(&myrpt
->remlock
);
3541 if (!strcmp(myrpt
->remote
,remote_rig_ic706
))
3543 set_mode_ic706(myrpt
, REM_MODE_AM
);
3544 if(play_tone(mychannel
, 800, 6000, 8192) == -1) break;
3545 ast_safe_sleep(mychannel
,500);
3546 set_mode_ic706(myrpt
, myrpt
->remmode
);
3547 myrpt
->tunerequest
= 0;
3548 ast_mutex_unlock(&myrpt
->remlock
);
3552 set_mode_ft897(myrpt
, REM_MODE_AM
);
3553 simple_command_ft897(myrpt
, 8);
3554 if(play_tone(mychannel
, 800, 6000, 8192) == -1) break;
3555 simple_command_ft897(myrpt
, 0x88);
3556 ast_safe_sleep(mychannel
,500);
3557 set_mode_ft897(myrpt
, myrpt
->remmode
);
3558 myrpt
->tunerequest
= 0;
3559 ast_mutex_unlock(&myrpt
->remlock
);
3562 case REMSHORTSTATUS
:
3564 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3565 res
= sayfile(mychannel
,"rpt/node");
3567 res
= saycharstr(mychannel
, myrpt
->name
);
3569 res
= sayfile(mychannel
,"rpt/frequency");
3571 res
= split_freq(mhz
, decimals
, myrpt
->freq
);
3572 if (!multimode_capable(myrpt
)) decimals
[3] = 0;
3576 res
= saynum(mychannel
, m
);
3578 res
= saycharstr(mychannel
, mhz
);
3581 res
= sayfile(mychannel
, "letters/dot");
3583 res
= saycharstr(mychannel
, decimals
);
3586 if(myrpt
->remmode
== REM_MODE_FM
){ /* Mode FM? */
3587 switch(myrpt
->offset
){
3590 res
= sayfile(mychannel
,"rpt/minus");
3594 res
= sayfile(mychannel
,"rpt/simplex");
3598 res
= sayfile(mychannel
,"rpt/plus");
3605 else{ /* Must be USB, LSB, or AM */
3606 switch(myrpt
->remmode
){
3609 res
= saycharstr(mychannel
, "USB");
3613 res
= saycharstr(mychannel
, "LSB");
3617 res
= saycharstr(mychannel
, "AM");
3626 if (res
== -1) break;
3628 if(mytele
->mode
== REMSHORTSTATUS
){ /* Short status? */
3629 wait_interval(myrpt
, DLY_COMP
, mychannel
);
3630 if (!res
) res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "functcomplete");
3634 if (strcmp(myrpt
->remote
,remote_rig_ic706
))
3636 switch(myrpt
->powerlevel
){
3639 res
= sayfile(mychannel
,"rpt/lopwr") ;
3642 res
= sayfile(mychannel
,"rpt/medpwr");
3645 res
= sayfile(mychannel
,"rpt/hipwr");
3650 rbimode
= ((!strncmp(myrpt
->remote
,remote_rig_rbi
,3))
3651 || (!strncmp(myrpt
->remote
,remote_rig_ic706
,3)));
3652 if (res
|| (sayfile(mychannel
,"rpt/rxpl") == -1)) break;
3653 if (rbimode
&& (sayfile(mychannel
,"rpt/txpl") == -1)) break;
3654 if ((sayfile(mychannel
,"rpt/frequency") == -1) ||
3655 (saycharstr(mychannel
,myrpt
->rxpl
) == -1)) break;
3656 if ((!rbimode
) && ((sayfile(mychannel
,"rpt/txpl") == -1) ||
3657 (sayfile(mychannel
,"rpt/frequency") == -1) ||
3658 (saycharstr(mychannel
,myrpt
->txpl
) == -1))) break;
3659 if(myrpt
->remmode
== REM_MODE_FM
){ /* Mode FM? */
3660 if ((sayfile(mychannel
,"rpt/rxpl") == -1) ||
3661 (sayfile(mychannel
,((myrpt
->rxplon
) ? "rpt/on" : "rpt/off")) == -1) ||
3662 (sayfile(mychannel
,"rpt/txpl") == -1) ||
3663 (sayfile(mychannel
,((myrpt
->txplon
) ? "rpt/on" : "rpt/off")) == -1))
3668 wait_interval(myrpt
, DLY_COMP
, mychannel
);
3669 if (!res
) res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "functcomplete");
3672 /* wait a little bit */
3673 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3675 linkbase
.next
= &linkbase
;
3676 linkbase
.prev
= &linkbase
;
3677 rpt_mutex_lock(&myrpt
->lock
);
3678 /* make our own list of links */
3679 l
= myrpt
->links
.next
;
3680 while(l
!= &myrpt
->links
)
3682 if (l
->name
[0] == '0')
3687 l1
= malloc(sizeof(struct rpt_link
));
3690 ast_log(LOG_WARNING
, "Cannot alloc memory on %s\n", mychannel
->name
);
3691 remque((struct qelem
*)mytele
);
3692 rpt_mutex_unlock(&myrpt
->lock
);
3693 ast_log(LOG_NOTICE
,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__
, mytele
->mode
); /*@@@@@@@@@@@*/
3695 ast_hangup(mychannel
);
3698 memcpy(l1
,l
,sizeof(struct rpt_link
));
3699 l1
->next
= l1
->prev
= NULL
;
3700 insque((struct qelem
*)l1
,(struct qelem
*)linkbase
.next
);
3703 rpt_mutex_unlock(&myrpt
->lock
);
3704 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3706 res
= ast_waitstream(mychannel
, "");
3708 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3709 ast_stopstream(mychannel
);
3710 ast_say_character_str(mychannel
,myrpt
->name
,NULL
,mychannel
->language
);
3712 res
= ast_waitstream(mychannel
, "");
3714 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3715 ast_stopstream(mychannel
);
3716 if (myrpt
->callmode
)
3719 res
= ast_streamfile(mychannel
, "rpt/autopatch_on", mychannel
->language
);
3721 res
= ast_waitstream(mychannel
, "");
3723 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3724 ast_stopstream(mychannel
);
3727 while(l
!= &linkbase
)
3732 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3734 res
= ast_waitstream(mychannel
, "");
3736 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3737 ast_stopstream(mychannel
);
3738 ast_say_character_str(mychannel
,l
->name
,NULL
,mychannel
->language
);
3740 res
= ast_waitstream(mychannel
, "");
3742 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3743 ast_stopstream(mychannel
);
3744 s
= "rpt/tranceive";
3745 if (!l
->mode
) s
= "rpt/monitor";
3746 if (!l
->thisconnected
) s
= "rpt/connecting";
3747 res
= ast_streamfile(mychannel
, s
, mychannel
->language
);
3749 res
= ast_waitstream(mychannel
, "");
3751 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3752 ast_stopstream(mychannel
);
3757 res
= ast_streamfile(mychannel
, "rpt/repeat_only", mychannel
->language
);
3759 res
= ast_waitstream(mychannel
, "");
3761 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3762 ast_stopstream(mychannel
);
3764 /* destroy our local link queue */
3766 while(l
!= &linkbase
)
3770 remque((struct qelem
*)l1
);
3776 rpt_mutex_lock(&myrpt
->lock
);
3777 /* get all the nodes */
3778 __mklinklist(myrpt
,NULL
,lbuf
);
3779 rpt_mutex_unlock(&myrpt
->lock
);
3781 ns
= finddelim(lbuf
,strs
,MAXLINKLIST
);
3783 if (ns
) qsort((void *)strs
,ns
,sizeof(char *),mycompar
);
3784 /* wait a little bit */
3785 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3787 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3789 res
= ast_waitstream(mychannel
, "");
3791 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3792 ast_stopstream(mychannel
);
3793 ast_say_character_str(mychannel
,myrpt
->name
,NULL
,mychannel
->language
);
3795 res
= ast_waitstream(mychannel
, "");
3797 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3798 ast_stopstream(mychannel
);
3799 if (myrpt
->callmode
)
3802 res
= ast_streamfile(mychannel
, "rpt/autopatch_on", mychannel
->language
);
3804 res
= ast_waitstream(mychannel
, "");
3806 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3807 ast_stopstream(mychannel
);
3809 /* go thru all the nodes in list */
3810 for(i
= 0; i
< ns
; i
++)
3814 /* if a mode spec at first, handle it */
3815 if ((*strs
[i
] < '0') || (*strs
[i
] > '9'))
3822 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3824 res
= ast_waitstream(mychannel
, "");
3826 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3827 ast_stopstream(mychannel
);
3828 ast_say_character_str(mychannel
,strs
[i
],NULL
,mychannel
->language
);
3830 res
= ast_waitstream(mychannel
, "");
3832 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3833 ast_stopstream(mychannel
);
3834 s
= "rpt/tranceive";
3835 if (mode
== 'R') s
= "rpt/monitor";
3836 if (mode
== 'C') s
= "rpt/connecting";
3837 res
= ast_streamfile(mychannel
, s
, mychannel
->language
);
3839 res
= ast_waitstream(mychannel
, "");
3841 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3842 ast_stopstream(mychannel
);
3846 res
= ast_streamfile(mychannel
, "rpt/repeat_only", mychannel
->language
);
3848 res
= ast_waitstream(mychannel
, "");
3850 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3851 ast_stopstream(mychannel
);
3856 case LASTNODEKEY
: /* Identify last node which keyed us up */
3857 rpt_mutex_lock(&myrpt
->lock
);
3858 if(myrpt
->lastnodewhichkeyedusup
)
3859 p
= ast_strdupa(myrpt
->lastnodewhichkeyedusup
); /* Make a local copy of the node name */
3862 rpt_mutex_unlock(&myrpt
->lock
);
3864 imdone
= 1; /* no node previously keyed us up, or the node which did has been disconnected */
3867 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3868 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3870 res
= ast_waitstream(mychannel
, "");
3872 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3873 ast_stopstream(mychannel
);
3874 ast_say_character_str(mychannel
, p
, NULL
, mychannel
->language
);
3876 res
= ast_waitstream(mychannel
, "");
3878 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3879 ast_stopstream(mychannel
);
3883 case UNAUTHTX
: /* Say unauthorized transmit frequency */
3884 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3885 res
= ast_streamfile(mychannel
, "rpt/unauthtx", mychannel
->language
);
3887 res
= ast_waitstream(mychannel
, "");
3889 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3890 ast_stopstream(mychannel
);
3896 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3898 res
= ast_waitstream(mychannel
, "");
3900 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3901 ast_stopstream(mychannel
);
3902 ast_say_character_str(mychannel
,myrpt
->name
,NULL
,mychannel
->language
);
3903 res
= ast_streamfile(mychannel
, "rpt/timeout", mychannel
->language
);
3906 case TIMEOUT_WARNING
:
3908 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3910 res
= ast_waitstream(mychannel
, "");
3912 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3913 ast_stopstream(mychannel
);
3914 ast_say_character_str(mychannel
,myrpt
->name
,NULL
,mychannel
->language
);
3915 res
= ast_streamfile(mychannel
, "rpt/timeout-warning", mychannel
->language
);
3917 res
= ast_waitstream(mychannel
, "");
3919 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3920 ast_stopstream(mychannel
);
3921 if(!res
) /* Say number of seconds */
3922 ast_say_number(mychannel
, myrpt
->p
.remotetimeout
-
3923 (t
- myrpt
->last_activity_time
),
3924 "", mychannel
->language
, (char *) NULL
);
3926 res
= ast_waitstream(mychannel
, "");
3927 ast_stopstream(mychannel
);
3928 res
= ast_streamfile(mychannel
, "queue-seconds", mychannel
->language
);
3931 case ACT_TIMEOUT_WARNING
:
3933 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3935 res
= ast_waitstream(mychannel
, "");
3937 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3938 ast_stopstream(mychannel
);
3939 ast_say_character_str(mychannel
,myrpt
->name
,NULL
,mychannel
->language
);
3940 res
= ast_streamfile(mychannel
, "rpt/act-timeout-warning", mychannel
->language
);
3942 res
= ast_waitstream(mychannel
, "");
3944 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3945 ast_stopstream(mychannel
);
3946 if(!res
) /* Say number of seconds */
3947 ast_say_number(mychannel
, myrpt
->p
.remoteinacttimeout
-
3948 (t
- myrpt
->last_activity_time
),
3949 "", mychannel
->language
, (char *) NULL
);
3951 res
= ast_waitstream(mychannel
, "");
3952 ast_stopstream(mychannel
);
3953 res
= ast_streamfile(mychannel
, "queue-seconds", mychannel
->language
);
3957 wait_interval(myrpt
, DLY_TELEM
, mychannel
); /* Wait a little bit */
3959 rpt_localtime(&t
, &localtm
);
3960 /* Say the phase of the day is before the time */
3961 if((localtm
.tm_hour
>= 0) && (localtm
.tm_hour
< 12))
3962 p
= "rpt/goodmorning";
3963 else if((localtm
.tm_hour
>= 12) && (localtm
.tm_hour
< 18))
3964 p
= "rpt/goodafternoon";
3966 p
= "rpt/goodevening";
3967 if (sayfile(mychannel
,p
) == -1)
3972 /* Say the time is ... */
3973 if (sayfile(mychannel
,"rpt/thetimeis") == -1)
3979 res
= ast_say_time(mychannel
, t
, "", mychannel
->language
);
3981 res
= ast_waitstream(mychannel
, "");
3982 ast_stopstream(mychannel
);
3986 p
= strstr(tdesc
, "version");
3989 if(sscanf(p
, "version %d.%d", &vmajor
, &vminor
) != 2)
3991 wait_interval(myrpt
, DLY_TELEM
, mychannel
); /* Wait a little bit */
3993 if (sayfile(mychannel
,"rpt/version") == -1)
3998 if(!res
) /* Say "X" */
3999 ast_say_number(mychannel
, vmajor
, "", mychannel
->language
, (char *) NULL
);
4001 res
= ast_waitstream(mychannel
, "");
4002 ast_stopstream(mychannel
);
4003 if (saycharstr(mychannel
,".") == -1)
4008 if(!res
) /* Say "Y" */
4009 ast_say_number(mychannel
, vminor
, "", mychannel
->language
, (char *) NULL
);
4011 res
= ast_waitstream(mychannel
, "");
4012 ast_stopstream(mychannel
);
4015 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
4019 wait_interval(myrpt
, DLY_TELEM
, mychannel
); /* Wait a little bit */
4021 saycharstr(mychannel
, mytele
->param
);
4025 wait_interval(myrpt
, DLY_TELEM
, mychannel
); /* Wait a little bit */
4028 /* Parts of this section taken from app_parkandannounce */
4029 char *tpl_working
, *tpl_current
;
4030 char *tmp
[100], *myparm
;
4031 int looptemp
=0,i
=0, dres
= 0;
4034 tpl_working
= strdupa(mytele
->param
);
4035 myparm
= strsep(&tpl_working
,",");
4036 tpl_current
=strsep(&tpl_working
, ":");
4038 while(tpl_current
&& looptemp
< sizeof(tmp
)) {
4039 tmp
[looptemp
]=tpl_current
;
4041 tpl_current
=strsep(&tpl_working
,":");
4044 for(i
=0; i
<looptemp
; i
++) {
4045 if(!strcmp(tmp
[i
], "PARKED")) {
4046 ast_say_digits(mychannel
, atoi(myparm
), "", mychannel
->language
);
4047 } else if(!strcmp(tmp
[i
], "NODE")) {
4048 ast_say_digits(mychannel
, atoi(myrpt
->name
), "", mychannel
->language
);
4050 dres
= ast_streamfile(mychannel
, tmp
[i
], mychannel
->language
);
4052 dres
= ast_waitstream(mychannel
, "");
4054 ast_log(LOG_WARNING
, "ast_streamfile of %s failed on %s\n", tmp
[i
], mychannel
->name
);
4064 if (myrpt
->stopgen
) break;
4065 myrpt
->stopgen
= -1;
4066 if ((res
= ast_tonepair_start(mychannel
, 1004.0, 0, 99999999, 7200.0)))
4071 while(mychannel
->generatordata
&& (myrpt
->stopgen
<= 0)) {
4072 if (ast_safe_sleep(mychannel
,1)) break;
4083 res
= ast_waitstream(mychannel
, "");
4085 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
4089 ast_stopstream(mychannel
);
4090 rpt_mutex_lock(&myrpt
->lock
);
4091 if (mytele
->mode
== TAILMSG
)
4095 myrpt
->tailmessagen
++;
4096 if(myrpt
->tailmessagen
>= myrpt
->p
.tailmessagemax
) myrpt
->tailmessagen
= 0;
4100 myrpt
->tmsgtimer
= myrpt
->p
.tailsquashedtime
;
4103 remque((struct qelem
*)mytele
);
4104 rpt_mutex_unlock(&myrpt
->lock
);
4106 ast_hangup(mychannel
);
4107 #ifdef APP_RPT_LOCK_DEBUG
4109 struct lockthread
*t
;
4112 ast_mutex_lock(&locklock
);
4113 t
= get_lockthread(pthread_self());
4114 if (t
) memset(t
,0,sizeof(struct lockthread
));
4115 ast_mutex_unlock(&locklock
);
4121 static void rpt_telemetry(struct rpt
*myrpt
,int mode
, void *data
)
4123 struct rpt_tele
*tele
;
4124 struct rpt_link
*mylink
= (struct rpt_link
*) data
;
4126 pthread_attr_t attr
;
4128 tele
= malloc(sizeof(struct rpt_tele
));
4131 ast_log(LOG_WARNING
, "Unable to allocate memory\n");
4136 memset((char *)tele
,0,sizeof(struct rpt_tele
));
4139 rpt_mutex_lock(&myrpt
->lock
);
4140 if((mode
== CONNFAIL
) || (mode
== REMDISC
) || (mode
== CONNECTED
) ||
4141 (mode
== LINKUNKEY
)){
4142 memset(&tele
->mylink
,0,sizeof(struct rpt_link
));
4144 memcpy(&tele
->mylink
,mylink
,sizeof(struct rpt_link
));
4147 else if ((mode
== ARB_ALPHA
) || (mode
== REV_PATCH
)) {
4148 strncpy(tele
->param
, (char *) data
, TELEPARAMSIZE
- 1);
4149 tele
->param
[TELEPARAMSIZE
- 1] = 0;
4151 if (mode
== REMXXX
) tele
->submode
= (int) data
;
4152 insque((struct qelem
*)tele
, (struct qelem
*)myrpt
->tele
.next
);
4153 rpt_mutex_unlock(&myrpt
->lock
);
4154 pthread_attr_init(&attr
);
4155 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
4156 res
= ast_pthread_create(&tele
->threadid
,&attr
,rpt_tele_thread
,(void *) tele
);
4158 rpt_mutex_lock(&myrpt
->lock
);
4159 remque((struct qlem
*) tele
); /* We don't like stuck transmitters, remove it from the queue */
4160 rpt_mutex_unlock(&myrpt
->lock
);
4161 ast_log(LOG_WARNING
, "Could not create telemetry thread: %s",strerror(res
));
4166 static void *rpt_call(void *this)
4168 ZT_CONFINFO ci
; /* conference info */
4169 struct rpt
*myrpt
= (struct rpt
*)this;
4171 int stopped
,congstarted
,dialtimer
,lastcidx
,aborted
;
4172 struct ast_channel
*mychannel
,*genchannel
;
4176 /* allocate a pseudo-channel thru asterisk */
4177 mychannel
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
4180 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
4183 #ifdef AST_CDR_FLAG_POST_DISABLED
4184 ast_set_flag(mychannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
4187 ci
.confno
= myrpt
->conf
; /* use the pseudo conference */
4188 ci
.confmode
= ZT_CONF_REALANDPSEUDO
| ZT_CONF_TALKER
| ZT_CONF_LISTENER
4189 | ZT_CONF_PSEUDO_TALKER
| ZT_CONF_PSEUDO_LISTENER
;
4190 /* first put the channel on the conference */
4191 if (ioctl(mychannel
->fds
[0],ZT_SETCONF
,&ci
) == -1)
4193 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
4194 ast_hangup(mychannel
);
4195 myrpt
->callmode
= 0;
4198 /* allocate a pseudo-channel thru asterisk */
4199 genchannel
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
4202 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
4203 ast_hangup(mychannel
);
4206 #ifdef AST_CDR_FLAG_POST_DISABLED
4207 ast_set_flag(genchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
4210 ci
.confno
= myrpt
->conf
;
4211 ci
.confmode
= ZT_CONF_REALANDPSEUDO
| ZT_CONF_TALKER
| ZT_CONF_LISTENER
4212 | ZT_CONF_PSEUDO_TALKER
| ZT_CONF_PSEUDO_LISTENER
;
4213 /* first put the channel on the conference */
4214 if (ioctl(genchannel
->fds
[0],ZT_SETCONF
,&ci
) == -1)
4216 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
4217 ast_hangup(mychannel
);
4218 ast_hangup(genchannel
);
4219 myrpt
->callmode
= 0;
4222 if (myrpt
->p
.tonezone
&& (tone_zone_set_zone(mychannel
->fds
[0],myrpt
->p
.tonezone
) == -1))
4224 ast_log(LOG_WARNING
, "Unable to set tone zone %s\n",myrpt
->p
.tonezone
);
4225 ast_hangup(mychannel
);
4226 ast_hangup(genchannel
);
4227 myrpt
->callmode
= 0;
4230 if (myrpt
->p
.tonezone
&& (tone_zone_set_zone(genchannel
->fds
[0],myrpt
->p
.tonezone
) == -1))
4232 ast_log(LOG_WARNING
, "Unable to set tone zone %s\n",myrpt
->p
.tonezone
);
4233 ast_hangup(mychannel
);
4234 ast_hangup(genchannel
);
4235 myrpt
->callmode
= 0;
4238 /* start dialtone if patchquiet is 0. Special patch modes don't send dial tone */
4239 if ((!myrpt
->patchquiet
) && (tone_zone_play_tone(mychannel
->fds
[0],ZT_TONE_DIALTONE
) < 0))
4241 ast_log(LOG_WARNING
, "Cannot start dialtone\n");
4242 ast_hangup(mychannel
);
4243 ast_hangup(genchannel
);
4244 myrpt
->callmode
= 0;
4254 while ((myrpt
->callmode
== 1) || (myrpt
->callmode
== 4))
4257 if((myrpt
->patchdialtime
)&&(myrpt
->callmode
== 1)&&(myrpt
->cidx
!= lastcidx
)){
4259 lastcidx
= myrpt
->cidx
;
4262 if((myrpt
->patchdialtime
)&&(dialtimer
>= myrpt
->patchdialtime
)){
4263 rpt_mutex_lock(&myrpt
->lock
);
4265 myrpt
->callmode
= 0;
4266 rpt_mutex_unlock(&myrpt
->lock
);
4270 if ((!myrpt
->patchquiet
) && (!stopped
) && (myrpt
->callmode
== 1) && (myrpt
->cidx
> 0))
4273 /* stop dial tone */
4274 tone_zone_play_tone(mychannel
->fds
[0],-1);
4276 if (myrpt
->callmode
== 4)
4280 /* start congestion tone */
4281 tone_zone_play_tone(mychannel
->fds
[0],ZT_TONE_CONGESTION
);
4284 res
= ast_safe_sleep(mychannel
, MSWAIT
);
4287 ast_hangup(mychannel
);
4288 ast_hangup(genchannel
);
4289 rpt_mutex_lock(&myrpt
->lock
);
4290 myrpt
->callmode
= 0;
4291 rpt_mutex_unlock(&myrpt
->lock
);
4294 dialtimer
+= MSWAIT
;
4296 /* stop any tone generation */
4297 tone_zone_play_tone(mychannel
->fds
[0],-1);
4299 if (!myrpt
->callmode
)
4301 ast_hangup(mychannel
);
4302 ast_hangup(genchannel
);
4303 rpt_mutex_lock(&myrpt
->lock
);
4304 myrpt
->callmode
= 0;
4305 rpt_mutex_unlock(&myrpt
->lock
);
4306 if((!myrpt
->patchquiet
) && aborted
)
4307 rpt_telemetry(myrpt
, TERM
, NULL
);
4311 if (myrpt
->p
.ourcallerid
&& *myrpt
->p
.ourcallerid
){
4312 char *name
, *loc
, *instr
;
4313 instr
= strdup(myrpt
->p
.ourcallerid
);
4315 ast_callerid_parse(instr
, &name
, &loc
);
4317 if(mychannel
->cid
.cid_num
)
4318 free(mychannel
->cid
.cid_num
);
4319 mychannel
->cid
.cid_num
= strdup(loc
);
4322 if(mychannel
->cid
.cid_name
)
4323 free(mychannel
->cid
.cid_name
);
4324 mychannel
->cid
.cid_name
= strdup(name
);
4330 ast_copy_string(mychannel
->exten
, myrpt
->exten
, sizeof(mychannel
->exten
) - 1);
4331 ast_copy_string(mychannel
->context
, myrpt
->patchcontext
, sizeof(mychannel
->context
) - 1);
4333 if (myrpt
->p
.acctcode
)
4334 ast_cdr_setaccount(mychannel
,myrpt
->p
.acctcode
);
4335 mychannel
->priority
= 1;
4336 ast_channel_undefer_dtmf(mychannel
);
4337 if (ast_pbx_start(mychannel
) < 0)
4339 ast_log(LOG_WARNING
, "Unable to start PBX!!\n");
4340 ast_hangup(mychannel
);
4341 ast_hangup(genchannel
);
4342 rpt_mutex_lock(&myrpt
->lock
);
4343 myrpt
->callmode
= 0;
4344 rpt_mutex_unlock(&myrpt
->lock
);
4348 rpt_mutex_lock(&myrpt
->lock
);
4349 myrpt
->callmode
= 3;
4350 /* set appropriate conference for the pseudo */
4352 ci
.confno
= myrpt
->conf
;
4353 ci
.confmode
= (myrpt
->p
.duplex
== 2) ? ZT_CONF_CONFANNMON
:
4354 (ZT_CONF_CONF
| ZT_CONF_LISTENER
| ZT_CONF_TALKER
);
4355 /* first put the channel on the conference in announce mode */
4356 if (ioctl(myrpt
->pchannel
->fds
[0],ZT_SETCONF
,&ci
) == -1)
4358 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
4359 ast_hangup(mychannel
);
4360 ast_hangup(genchannel
);
4361 myrpt
->callmode
= 0;
4364 while(myrpt
->callmode
)
4366 if ((!mychannel
->pbx
) && (myrpt
->callmode
!= 4))
4368 if(myrpt
->patchfarenddisconnect
){ /* If patch is setup for far end disconnect */
4369 myrpt
->callmode
= 0;
4370 if(!myrpt
->patchquiet
){
4371 rpt_mutex_unlock(&myrpt
->lock
);
4372 rpt_telemetry(myrpt
, TERM
, NULL
);
4373 rpt_mutex_lock(&myrpt
->lock
);
4376 else{ /* Send congestion until patch is downed by command */
4377 myrpt
->callmode
= 4;
4378 rpt_mutex_unlock(&myrpt
->lock
);
4379 /* start congestion tone */
4380 tone_zone_play_tone(genchannel
->fds
[0],ZT_TONE_CONGESTION
);
4381 rpt_mutex_lock(&myrpt
->lock
);
4386 struct ast_frame wf
= {AST_FRAME_DTMF
, } ;
4387 wf
.subclass
= myrpt
->mydtmf
;
4388 rpt_mutex_unlock(&myrpt
->lock
);
4389 ast_queue_frame(mychannel
,&wf
);
4390 ast_senddigit(genchannel
,myrpt
->mydtmf
);
4391 rpt_mutex_lock(&myrpt
->lock
);
4394 rpt_mutex_unlock(&myrpt
->lock
);
4395 usleep(MSWAIT
* 1000);
4396 rpt_mutex_lock(&myrpt
->lock
);
4398 rpt_mutex_unlock(&myrpt
->lock
);
4399 tone_zone_play_tone(genchannel
->fds
[0],-1);
4400 if (mychannel
->pbx
) ast_softhangup(mychannel
,AST_SOFTHANGUP_DEV
);
4401 ast_hangup(genchannel
);
4402 rpt_mutex_lock(&myrpt
->lock
);
4403 myrpt
->callmode
= 0;
4404 rpt_mutex_unlock(&myrpt
->lock
);
4405 /* set appropriate conference for the pseudo */
4407 ci
.confno
= myrpt
->conf
;
4408 ci
.confmode
= ((myrpt
->p
.duplex
== 2) || (myrpt
->p
.duplex
== 4)) ? ZT_CONF_CONFANNMON
:
4409 (ZT_CONF_CONF
| ZT_CONF_LISTENER
| ZT_CONF_TALKER
);
4410 /* first put the channel on the conference in announce mode */
4411 if (ioctl(myrpt
->pchannel
->fds
[0],ZT_SETCONF
,&ci
) == -1)
4413 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
4418 static void send_link_dtmf(struct rpt
*myrpt
,char c
)
4421 struct ast_frame wf
;
4424 snprintf(str
, sizeof(str
), "D %s %s %d %c", myrpt
->cmdnode
, myrpt
->name
, ++(myrpt
->dtmfidx
), c
);
4425 wf
.frametype
= AST_FRAME_TEXT
;
4429 wf
.datalen
= strlen(str
) + 1;
4431 l
= myrpt
->links
.next
;
4432 /* first, see if our dude is there */
4433 while(l
!= &myrpt
->links
)
4435 if (l
->name
[0] == '0')
4440 /* if we found it, write it and were done */
4441 if (!strcmp(l
->name
,myrpt
->cmdnode
))
4444 if (l
->chan
) ast_write(l
->chan
,&wf
);
4449 l
= myrpt
->links
.next
;
4450 /* if not, give it to everyone */
4451 while(l
!= &myrpt
->links
)
4454 if (l
->chan
) ast_write(l
->chan
,&wf
);
4467 * 2: Already connected to this node
4470 static int connect_link(struct rpt
*myrpt
, char* node
, int mode
, int perma
)
4472 char *val
, *s
, *s1
, *s2
, *tele
;
4473 char lstr
[MAXLINKLIST
],*strs
[MAXLINKLIST
];
4474 char tmp
[300], deststr
[300] = "",modechange
= 0;
4478 ZT_CONFINFO ci
; /* conference info */
4480 val
= node_lookup(myrpt
,node
);
4482 if(strlen(node
) >= myrpt
->longestnode
)
4483 return -1; /* No such node */
4484 return 1; /* No match yet */
4487 ast_log(LOG_NOTICE
,"Connect attempt to node %s\n", node
);
4488 ast_log(LOG_NOTICE
,"Mode: %s\n",(mode
)?"Transceive":"Monitor");
4489 ast_log(LOG_NOTICE
,"Connection type: %s\n",(perma
)?"Permalink":"Normal");
4492 strncpy(tmp
,val
,sizeof(tmp
) - 1);
4494 s1
= strsep(&s
,",");
4495 s2
= strsep(&s
,",");
4496 rpt_mutex_lock(&myrpt
->lock
);
4497 l
= myrpt
->links
.next
;
4498 /* try to find this one in queue */
4499 while(l
!= &myrpt
->links
){
4500 if (l
->name
[0] == '0')
4505 /* if found matching string */
4506 if (!strcmp(l
->name
, node
))
4511 if (l
!= &myrpt
->links
){
4512 /* if already in this mode, just ignore */
4513 if ((l
->mode
) || (!l
->chan
)) {
4514 rpt_mutex_unlock(&myrpt
->lock
);
4515 return 2; /* Already linked */
4517 reconnects
= l
->reconnects
;
4518 rpt_mutex_unlock(&myrpt
->lock
);
4519 if (l
->chan
) ast_softhangup(l
->chan
, AST_SOFTHANGUP_DEV
);
4520 l
->retries
= l
->max_retries
+ 1;
4525 __mklinklist(myrpt
,NULL
,lstr
);
4526 rpt_mutex_unlock(&myrpt
->lock
);
4527 n
= finddelim(lstr
,strs
,MAXLINKLIST
);
4528 for(i
= 0; i
< n
; i
++)
4530 if ((*strs
[i
] < '0') ||
4531 (*strs
[i
] > '9')) strs
[i
]++;
4532 if (!strcmp(strs
[i
],node
))
4534 return 2; /* Already linked */
4538 strncpy(myrpt
->lastlinknode
,node
,MAXNODESTR
- 1);
4539 /* establish call */
4540 l
= malloc(sizeof(struct rpt_link
));
4543 ast_log(LOG_WARNING
, "Unable to malloc\n");
4546 /* zero the silly thing */
4547 memset((char *)l
,0,sizeof(struct rpt_link
));
4550 l
->thisconnected
= 0;
4551 strncpy(l
->name
, node
, MAXNODESTR
- 1);
4552 l
->isremote
= (s
&& ast_true(s
));
4553 if (modechange
) l
->connected
= 1;
4554 l
->hasconnected
= l
->perma
= perma
;
4555 #ifdef ALLOW_LOCAL_CHANNELS
4556 if ((strncasecmp(s1
,"iax2/", 5) == 0) || (strncasecmp(s1
, "local/", 6) == 0))
4557 strncpy(deststr
, s1
, sizeof(deststr
));
4559 snprintf(deststr
, sizeof(deststr
), "IAX2/%s", s1
);
4561 snprintf(deststr
, sizeof(deststr
), "IAX2/%s", s1
);
4563 tele
= strchr(deststr
, '/');
4565 ast_log(LOG_WARNING
,"link3:Dial number (%s) must be in format tech/number\n",deststr
);
4570 l
->chan
= ast_request(deststr
, AST_FORMAT_SLINEAR
, tele
,NULL
);
4572 ast_set_read_format(l
->chan
, AST_FORMAT_SLINEAR
);
4573 ast_set_write_format(l
->chan
, AST_FORMAT_SLINEAR
);
4574 #ifdef AST_CDR_FLAG_POST_DISABLED
4575 ast_set_flag(l
->chan
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
4577 l
->chan
->whentohangup
= 0;
4578 l
->chan
->appl
= "Apprpt";
4579 l
->chan
->data
= "(Remote Rx)";
4581 ast_log(LOG_NOTICE
, "rpt (remote) initiating call to %s/%s on %s\n",
4582 deststr
, tele
, l
->chan
->name
);
4583 if(l
->chan
->cid
.cid_num
)
4584 free(l
->chan
->cid
.cid_num
);
4585 l
->chan
->cid
.cid_num
= strdup(myrpt
->name
);
4586 ast_call(l
->chan
,tele
,999);
4590 ast_log(LOG_NOTICE
, "Unable to place call to %s/%s on %s\n",
4591 deststr
,tele
,l
->chan
->name
);
4592 if (myrpt
->p
.archivedir
)
4595 sprintf(str
,"LINKFAIL,%s",l
->name
);
4596 donodelog(myrpt
,str
);
4601 /* allocate a pseudo-channel thru asterisk */
4602 l
->pchan
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
4604 ast_log(LOG_WARNING
,"rpt connect: Sorry unable to obtain pseudo channel\n");
4605 ast_hangup(l
->chan
);
4609 ast_set_read_format(l
->pchan
, AST_FORMAT_SLINEAR
);
4610 ast_set_write_format(l
->pchan
, AST_FORMAT_SLINEAR
);
4611 #ifdef AST_CDR_FLAG_POST_DISABLED
4612 ast_set_flag(l
->pchan
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
4614 /* make a conference for the tx */
4616 ci
.confno
= myrpt
->conf
;
4617 ci
.confmode
= ZT_CONF_CONF
| ZT_CONF_LISTENER
| ZT_CONF_TALKER
;
4618 /* first put the channel on the conference in proper mode */
4619 if (ioctl(l
->pchan
->fds
[0], ZT_SETCONF
, &ci
) == -1)
4621 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
4622 ast_hangup(l
->chan
);
4623 ast_hangup(l
->pchan
);
4627 rpt_mutex_lock(&myrpt
->lock
);
4628 l
->reconnects
= reconnects
;
4629 /* insert at end of queue */
4630 l
->max_retries
= MAX_RETRIES
;
4632 l
->max_retries
= MAX_RETRIES_PERM
;
4633 if (l
->isremote
) l
->retries
= l
->max_retries
+ 1;
4634 insque((struct qelem
*)l
,(struct qelem
*)myrpt
->links
.next
);
4636 rpt_mutex_unlock(&myrpt
->lock
);
4643 * Internet linking function
4646 static int function_ilink(struct rpt
*myrpt
, char *param
, char *digits
, int command_source
, struct rpt_link
*mylink
)
4649 char *val
, *s
, *s1
, *s2
;
4651 char digitbuf
[MAXNODESTR
],*strs
[MAXLINKLIST
];
4660 if (myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
|| myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].linkfundisable
)
4663 strncpy(digitbuf
,digits
,MAXNODESTR
- 1);
4666 printf("@@@@ ilink param = %s, digitbuf = %s\n", (param
)? param
: "(null)", digitbuf
);
4668 switch(myatoi(param
)){
4669 case 11: /* Perm Link off */
4670 case 1: /* Link off */
4671 if ((digitbuf
[0] == '0') && (myrpt
->lastlinknode
[0]))
4672 strcpy(digitbuf
,myrpt
->lastlinknode
);
4673 val
= node_lookup(myrpt
,digitbuf
);
4675 if(strlen(digitbuf
) >= myrpt
->longestnode
)
4679 strncpy(tmp
,val
,sizeof(tmp
) - 1);
4681 s1
= strsep(&s
,",");
4682 s2
= strsep(&s
,",");
4683 rpt_mutex_lock(&myrpt
->lock
);
4684 l
= myrpt
->links
.next
;
4685 /* try to find this one in queue */
4686 while(l
!= &myrpt
->links
){
4687 if (l
->name
[0] == '0')
4692 /* if found matching string */
4693 if (!strcmp(l
->name
, digitbuf
))
4697 if (l
!= &myrpt
->links
){ /* if found */
4698 struct ast_frame wf
;
4700 /* must use perm command on perm link */
4701 if ((myatoi(param
) < 10) &&
4702 (l
->max_retries
> MAX_RETRIES
))
4704 rpt_mutex_unlock(&myrpt
->lock
);
4707 strncpy(myrpt
->lastlinknode
,digitbuf
,MAXNODESTR
- 1);
4708 l
->retries
= l
->max_retries
+ 1;
4710 rpt_mutex_unlock(&myrpt
->lock
);
4711 wf
.frametype
= AST_FRAME_TEXT
;
4715 wf
.datalen
= strlen(discstr
) + 1;
4720 ast_write(l
->chan
,&wf
);
4721 if (ast_safe_sleep(l
->chan
,250) == -1) return DC_ERROR
;
4722 ast_softhangup(l
->chan
,AST_SOFTHANGUP_DEV
);
4724 rpt_telemetry(myrpt
, COMPLETE
, NULL
);
4727 rpt_mutex_unlock(&myrpt
->lock
);
4729 case 2: /* Link Monitor */
4730 case 3: /* Link transceive */
4731 case 12: /* Link Monitor permanent */
4732 case 13: /* Link transceive permanent */
4733 if ((digitbuf
[0] == '0') && (myrpt
->lastlinknode
[0]))
4734 strcpy(digitbuf
,myrpt
->lastlinknode
);
4735 /* Attempt connection */
4736 perma
= (atoi(param
) > 10) ? 1 : 0;
4737 mode
= (atoi(param
) & 1) ? 1 : 0;
4738 r
= connect_link(myrpt
, digitbuf
, mode
, perma
);
4741 rpt_telemetry(myrpt
, COMPLETE
, NULL
);
4748 rpt_telemetry(myrpt
, REMALREADY
, NULL
);
4752 rpt_telemetry(myrpt
, CONNFAIL
, NULL
);
4757 case 4: /* Enter Command Mode */
4759 /* if doesnt allow link cmd, or no links active, return */
4760 if (((command_source
!= SOURCE_RPT
) &&
4761 (command_source
!= SOURCE_PHONE
) &&
4762 (command_source
!= SOURCE_DPHONE
)) ||
4763 (myrpt
->links
.next
== &myrpt
->links
))
4766 /* if already in cmd mode, or selected self, fughetabahtit */
4767 if ((myrpt
->cmdnode
[0]) || (!strcmp(myrpt
->name
, digitbuf
))){
4769 rpt_telemetry(myrpt
, REMALREADY
, NULL
);
4772 if ((digitbuf
[0] == '0') && (myrpt
->lastlinknode
[0]))
4773 strcpy(digitbuf
,myrpt
->lastlinknode
);
4774 /* node must at least exist in list */
4775 val
= node_lookup(myrpt
,digitbuf
);
4777 if(strlen(digitbuf
) >= myrpt
->longestnode
)
4782 rpt_mutex_lock(&myrpt
->lock
);
4783 strcpy(myrpt
->lastlinknode
,digitbuf
);
4784 strncpy(myrpt
->cmdnode
, digitbuf
, sizeof(myrpt
->cmdnode
) - 1);
4785 rpt_mutex_unlock(&myrpt
->lock
);
4786 rpt_telemetry(myrpt
, REMGO
, NULL
);
4789 case 5: /* Status */
4790 rpt_telemetry(myrpt
, STATUS
, NULL
);
4793 case 15: /* Full Status */
4794 rpt_telemetry(myrpt
, FULLSTATUS
, NULL
);
4798 case 6: /* All Links Off, including permalinks */
4799 rpt_mutex_lock(&myrpt
->lock
);
4800 myrpt
->savednodes
[0] = 0;
4801 l
= myrpt
->links
.next
;
4802 /* loop through all links */
4803 while(l
!= &myrpt
->links
){
4804 struct ast_frame wf
;
4805 if (l
->name
[0] == '0') /* Skip any IAXRPT monitoring */
4810 /* Make a string of disconnected nodes for possible restoration */
4811 sprintf(tmp
,"%c%c%s",(l
->mode
) ? 'X' : 'M',(l
->perma
) ? 'P':'T',l
->name
);
4812 if(strlen(tmp
) + strlen(myrpt
->savednodes
) + 1 < MAXNODESTR
){
4813 if(myrpt
->savednodes
[0])
4814 strcat(myrpt
->savednodes
, ",");
4815 strcat(myrpt
->savednodes
, tmp
);
4817 l
->retries
= l
->max_retries
+ 1;
4818 l
->disced
= 2; /* Silently disconnect */
4819 rpt_mutex_unlock(&myrpt
->lock
);
4820 /* ast_log(LOG_NOTICE,"dumping link %s\n",l->name); */
4822 wf
.frametype
= AST_FRAME_TEXT
;
4826 wf
.datalen
= strlen(discstr
) + 1;
4831 ast_write(l
->chan
,&wf
);
4832 ast_safe_sleep(l
->chan
,250); /* It's dead already, why check the return value? */
4833 ast_softhangup(l
->chan
,AST_SOFTHANGUP_DEV
);
4835 rpt_mutex_lock(&myrpt
->lock
);
4838 rpt_mutex_unlock(&myrpt
->lock
);
4840 ast_log(LOG_NOTICE
,"Nodes disconnected: %s\n",myrpt
->savednodes
);
4841 rpt_telemetry(myrpt
, COMPLETE
, NULL
);
4844 case 7: /* Identify last node which keyed us up */
4845 rpt_telemetry(myrpt
, LASTNODEKEY
, NULL
);
4849 #ifdef _MDC_DECODE_H_
4851 myrpt
->lastunit
= 0xd00d;
4852 mdc1200_notify(myrpt
,NULL
,myrpt
->lastunit
);
4853 mdc1200_send(myrpt
,myrpt
->lastunit
);
4857 case 16: /* Restore links disconnected with "disconnect all links" command */
4858 strcpy(tmp
, myrpt
->savednodes
); /* Make a copy */
4859 finddelim(tmp
, strs
, MAXLINKLIST
); /* convert into substrings */
4860 for(i
= 0; tmp
[0] && strs
[i
] != NULL
&& i
< MAXLINKLIST
; i
++){
4862 mode
= (s1
[0] == 'X') ? 1 : 0;
4863 perma
= (s1
[1] == 'P') ? 1 : 0;
4864 connect_link(myrpt
, s1
+ 2, mode
, perma
); /* Try to reconnect */
4866 rpt_telemetry(myrpt
, COMPLETE
, NULL
);
4885 if (((myrpt
->p
.propagate_dtmf
) &&
4886 (command_source
== SOURCE_LNK
)) ||
4887 ((myrpt
->p
.propagate_phonedtmf
) &&
4888 ((command_source
== SOURCE_PHONE
) ||
4889 (command_source
== SOURCE_DPHONE
))))
4890 do_dtmf_local(myrpt
,
4891 remdtmfstr
[myatoi(param
) - 200]);
4897 return DC_INDETERMINATE
;
4904 static int function_autopatchup(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
4906 pthread_attr_t attr
;
4907 int i
, index
, paramlength
;
4910 char *paramlist
[20];
4912 static char *keywords
[] = {
4921 if (myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
|| myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].autopatchdisable
)
4925 printf("@@@@ Autopatch up\n");
4927 if(!myrpt
->callmode
){
4929 myrpt
->patchnoct
= 0;
4930 myrpt
->patchdialtime
= 0;
4931 myrpt
->patchfarenddisconnect
= 0;
4932 myrpt
->patchquiet
= 0;
4933 strncpy(myrpt
->patchcontext
, myrpt
->p
.ourcontext
, MAXPATCHCONTEXT
);
4936 /* Process parameter list */
4937 lparam
= ast_strdupa(param
);
4939 ast_log(LOG_ERROR
,"App_rpt out of memory on line %d\n",__LINE__
);
4942 paramlength
= finddelim(lparam
, paramlist
, 20);
4943 for(i
= 0; i
< paramlength
; i
++){
4944 index
= matchkeyword(paramlist
[i
], &value
, keywords
);
4946 value
= skipchars(value
, "= ");
4949 case 1: /* context */
4950 strncpy(myrpt
->patchcontext
, value
, MAXPATCHCONTEXT
- 1) ;
4953 case 2: /* dialtime */
4954 myrpt
->patchdialtime
= atoi(value
);
4957 case 3: /* farenddisconnect */
4958 myrpt
->patchfarenddisconnect
= atoi(value
);
4962 myrpt
->patchnoct
= atoi(value
);
4966 myrpt
->patchquiet
= atoi(value
);
4976 rpt_mutex_lock(&myrpt
->lock
);
4978 /* if on call, force * into current audio stream */
4980 if ((myrpt
->callmode
== 2) || (myrpt
->callmode
== 3)){
4981 myrpt
->mydtmf
= myrpt
->p
.endchar
;
4983 if (myrpt
->callmode
){
4984 rpt_mutex_unlock(&myrpt
->lock
);
4987 myrpt
->callmode
= 1;
4989 myrpt
->exten
[myrpt
->cidx
] = 0;
4990 rpt_mutex_unlock(&myrpt
->lock
);
4991 pthread_attr_init(&attr
);
4992 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
4993 ast_pthread_create(&myrpt
->rpt_call_thread
,&attr
,rpt_call
,(void *) myrpt
);
5001 static int function_autopatchdn(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
5003 if (myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
|| myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].autopatchdisable
)
5007 printf("@@@@ Autopatch down\n");
5009 rpt_mutex_lock(&myrpt
->lock
);
5011 if (!myrpt
->callmode
){
5012 rpt_mutex_unlock(&myrpt
->lock
);
5016 myrpt
->callmode
= 0;
5017 rpt_mutex_unlock(&myrpt
->lock
);
5018 rpt_telemetry(myrpt
, TERM
, NULL
);
5026 static int function_status(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
5032 if ((myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
) || (myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].userfundisable
))
5036 printf("@@@@ status param = %s, digitbuf = %s\n", (param
)? param
: "(null)", digitbuf
);
5038 switch(myatoi(param
)){
5039 case 1: /* System ID */
5040 rpt_telemetry(myrpt
, ID1
, NULL
);
5042 case 2: /* System Time */
5043 rpt_telemetry(myrpt
, STATS_TIME
, NULL
);
5045 case 3: /* app_rpt.c version */
5046 rpt_telemetry(myrpt
, STATS_VERSION
, NULL
);
5050 return DC_INDETERMINATE
;
5054 * Macro-oni (without Salami)
5057 static int function_macro(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
5066 printf("@@@@ macro-oni param = %s, digitbuf = %s\n", (param
)? param
: "(null)", digitbuf
);
5068 if(strlen(digitbuf
) < 1) /* needs 1 digit */
5069 return DC_INDETERMINATE
;
5071 for(i
= 0 ; i
< digitbuf
[i
] ; i
++) {
5072 if((digitbuf
[i
] < '0') || (digitbuf
[i
] > '9'))
5076 if (*digitbuf
== '0') val
= myrpt
->p
.startupmacro
;
5077 else val
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->p
.macro
, digitbuf
);
5078 /* param was 1 for local buf */
5080 if (strlen(digitbuf
) < myrpt
->macro_longest
)
5081 return DC_INDETERMINATE
;
5082 rpt_telemetry(myrpt
, MACRO_NOTFOUND
, NULL
);
5085 rpt_mutex_lock(&myrpt
->lock
);
5086 if ((MAXMACRO
- strlen(myrpt
->macrobuf
)) < strlen(val
))
5088 rpt_mutex_unlock(&myrpt
->lock
);
5089 rpt_telemetry(myrpt
, MACRO_BUSY
, NULL
);
5092 myrpt
->macrotimer
= MACROTIME
;
5093 strncat(myrpt
->macrobuf
,val
,MAXMACRO
- 1);
5094 rpt_mutex_unlock(&myrpt
->lock
);
5099 * COP - Control operator
5102 static int function_cop(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
5109 switch(myatoi(param
)){
5110 case 1: /* System reset */
5111 system("killall -9 asterisk");
5115 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
= 0;
5116 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "RPTENA");
5120 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
= 1;
5123 case 4: /* test tone on */
5124 if (myrpt
->stopgen
< 0)
5131 rpt_telemetry(myrpt
, TEST_TONE
, NULL
);
5135 case 5: /* Disgorge variables to log for debug purposes */
5136 myrpt
->disgorgetime
= time(NULL
) + 10; /* Do it 10 seconds later */
5139 case 6: /* Simulate COR being activated (phone only) */
5140 if (command_source
!= SOURCE_PHONE
) return DC_INDETERMINATE
;
5144 case 7: /* Time out timer enable */
5145 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].totdisable
= 0;
5146 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "TOTENA");
5149 case 8: /* Time out timer disable */
5150 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].totdisable
= 1;
5151 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "TOTDIS");
5154 case 9: /* Autopatch enable */
5155 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].autopatchdisable
= 0;
5156 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "APENA");
5159 case 10: /* Autopatch disable */
5160 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].autopatchdisable
= 1;
5161 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "APDIS");
5164 case 11: /* Link Enable */
5165 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].linkfundisable
= 0;
5166 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "LNKENA");
5169 case 12: /* Link Disable */
5170 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].linkfundisable
= 1;
5171 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "LNKDIS");
5174 case 13: /* Query System State */
5175 string
[0] = string
[1] = 'S';
5176 string
[2] = myrpt
->p
.sysstate_cur
+ '0';
5178 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) string
);
5181 case 14: /* Change System State */
5182 if(strlen(digitbuf
) == 0)
5184 if((digitbuf
[0] < '0') || (digitbuf
[0] > '9'))
5186 myrpt
->p
.sysstate_cur
= digitbuf
[0] - '0';
5187 string
[0] = string
[1] = 'S';
5188 string
[2] = myrpt
->p
.sysstate_cur
+ '0';
5190 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) string
);
5193 case 15: /* Scheduler Enable */
5194 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].schedulerdisable
= 0;
5195 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "SKENA");
5198 case 16: /* Scheduler Disable */
5199 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].schedulerdisable
= 1;
5200 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "SKDIS");
5203 case 17: /* User functions Enable */
5204 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].userfundisable
= 0;
5205 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "UFENA");
5208 case 18: /* User Functions Disable */
5209 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].userfundisable
= 1;
5210 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "UFDIS");
5213 case 19: /* Alternate Tail Enable */
5214 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].alternatetail
= 1;
5215 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "ATENA");
5218 case 20: /* Alternate Tail Disable */
5219 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].alternatetail
= 0;
5220 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "ATDIS");
5223 return DC_INDETERMINATE
;
5227 * Collect digits one by one until something matches
5230 static int collect_function_digits(struct rpt
*myrpt
, char *digits
,
5231 int command_source
, struct rpt_link
*mylink
)
5234 char *stringp
,*action
,*param
,*functiondigits
;
5235 char function_table_name
[30] = "";
5236 char workstring
[200];
5238 struct ast_variable
*vp
;
5241 printf("@@@@ Digits collected: %s, source: %d\n", digits
, command_source
);
5243 if (command_source
== SOURCE_DPHONE
) {
5244 if (!myrpt
->p
.dphone_functions
) return DC_INDETERMINATE
;
5245 strncpy(function_table_name
, myrpt
->p
.dphone_functions
, sizeof(function_table_name
) - 1);
5247 else if (command_source
== SOURCE_PHONE
) {
5248 if (!myrpt
->p
.phone_functions
) return DC_INDETERMINATE
;
5249 strncpy(function_table_name
, myrpt
->p
.phone_functions
, sizeof(function_table_name
) - 1);
5251 else if (command_source
== SOURCE_LNK
)
5252 strncpy(function_table_name
, myrpt
->p
.link_functions
, sizeof(function_table_name
) - 1);
5254 strncpy(function_table_name
, myrpt
->p
.functions
, sizeof(function_table_name
) - 1);
5255 vp
= ast_variable_browse(myrpt
->cfg
, function_table_name
);
5257 if(!strncasecmp(vp
->name
, digits
, strlen(vp
->name
)))
5264 n
= myrpt
->longestfunc
;
5265 if (command_source
== SOURCE_LNK
) n
= myrpt
->link_longestfunc
;
5267 if (command_source
== SOURCE_PHONE
) n
= myrpt
->phone_longestfunc
;
5269 if (command_source
== SOURCE_DPHONE
) n
= myrpt
->dphone_longestfunc
;
5271 if(strlen(digits
) >= n
)
5274 return DC_INDETERMINATE
;
5276 /* Found a match, retrieve value part and parse */
5277 strncpy(workstring
, vp
->value
, sizeof(workstring
) - 1 );
5278 stringp
= workstring
;
5279 action
= strsep(&stringp
, ",");
5282 printf("@@@@ action: %s, param = %s\n",action
, (param
) ? param
: "(null)");
5283 /* Look up the action */
5284 for(i
= 0 ; i
< (sizeof(function_table
)/sizeof(struct function_table_tag
)); i
++){
5285 if(!strncasecmp(action
, function_table
[i
].action
, strlen(action
)))
5289 printf("@@@@ table index i = %d\n",i
);
5290 if(i
== (sizeof(function_table
)/sizeof(struct function_table_tag
))){
5291 /* Error, action not in table */
5294 if(function_table
[i
].function
== NULL
){
5295 /* Error, function undefined */
5297 printf("@@@@ NULL for action: %s\n",action
);
5300 functiondigits
= digits
+ strlen(vp
->name
);
5301 return (*function_table
[i
].function
)(myrpt
, param
, functiondigits
, command_source
, mylink
);
5305 static void handle_link_data(struct rpt
*myrpt
, struct rpt_link
*mylink
,
5308 char tmp
[512],cmd
[300] = "",dest
[300],src
[300],c
;
5311 struct ast_frame wf
;
5313 wf
.frametype
= AST_FRAME_TEXT
;
5317 wf
.datalen
= strlen(str
) + 1;
5319 /* put string in our buffer */
5320 strncpy(tmp
,str
,sizeof(tmp
) - 1);
5322 if (!strcmp(tmp
,discstr
))
5325 mylink
->retries
= mylink
->max_retries
+ 1;
5326 ast_softhangup(mylink
->chan
,AST_SOFTHANGUP_DEV
);
5331 rpt_mutex_lock(&myrpt
->lock
);
5332 strcpy(mylink
->linklist
,tmp
+ 2);
5333 time(&mylink
->linklistreceived
);
5334 rpt_mutex_unlock(&myrpt
->lock
);
5335 if (debug
> 6) ast_log(LOG_NOTICE
,"@@@@ node %s recieved node list %s from node %s\n",
5336 myrpt
->name
,tmp
,mylink
->name
);
5341 if (sscanf(tmp
,"%s %s %x",cmd
,src
,&seq
) != 3)
5343 ast_log(LOG_WARNING
, "Unable to parse ident string %s\n",str
);
5346 mdc1200_notify(myrpt
,src
,seq
);
5351 if (sscanf(tmp
,"%s %s %s %d %c",cmd
,dest
,src
,&seq
,&c
) != 5)
5353 ast_log(LOG_WARNING
, "Unable to parse link string %s\n",str
);
5356 if (strcmp(cmd
,"D"))
5358 ast_log(LOG_WARNING
, "Unable to parse link string %s\n",str
);
5364 strcpy(dest
,myrpt
->name
);
5367 /* if not for me, redistribute to all links */
5368 if (strcmp(dest
,myrpt
->name
))
5370 l
= myrpt
->links
.next
;
5371 /* see if this is one in list */
5372 while(l
!= &myrpt
->links
)
5374 if (l
->name
[0] == '0')
5379 /* dont send back from where it came */
5380 if ((l
== mylink
) || (!strcmp(l
->name
,mylink
->name
)))
5385 /* if it is, send it and we're done */
5386 if (!strcmp(l
->name
,dest
))
5388 /* send, but not to src */
5389 if (strcmp(l
->name
,src
)) {
5391 if (l
->chan
) ast_write(l
->chan
,&wf
);
5397 l
= myrpt
->links
.next
;
5398 /* otherwise, send it to all of em */
5399 while(l
!= &myrpt
->links
)
5401 if (l
->name
[0] == '0')
5406 /* dont send back from where it came */
5407 if ((l
== mylink
) || (!strcmp(l
->name
,mylink
->name
)))
5412 /* send, but not to src */
5413 if (strcmp(l
->name
,src
)) {
5415 if (l
->chan
) ast_write(l
->chan
,&wf
);
5421 if (myrpt
->p
.archivedir
)
5425 sprintf(str
,"DTMF,%s,%c",mylink
->name
,c
);
5426 donodelog(myrpt
,str
);
5428 c
= func_xlat(myrpt
,c
,&myrpt
->p
.outxlat
);
5430 rpt_mutex_lock(&myrpt
->lock
);
5431 if (c
== myrpt
->p
.endchar
) myrpt
->stopgen
= 1;
5432 if (myrpt
->callmode
== 1)
5434 myrpt
->exten
[myrpt
->cidx
++] = c
;
5435 myrpt
->exten
[myrpt
->cidx
] = 0;
5436 /* if this exists */
5437 if (ast_exists_extension(myrpt
->pchannel
,myrpt
->patchcontext
,myrpt
->exten
,1,NULL
))
5439 myrpt
->callmode
= 2;
5440 if(!myrpt
->patchquiet
){
5441 rpt_mutex_unlock(&myrpt
->lock
);
5442 rpt_telemetry(myrpt
,PROC
,NULL
);
5443 rpt_mutex_lock(&myrpt
->lock
);
5446 /* if can continue, do so */
5447 if (!ast_canmatch_extension(myrpt
->pchannel
,myrpt
->patchcontext
,myrpt
->exten
,1,NULL
))
5449 /* call has failed, inform user */
5450 myrpt
->callmode
= 4;
5453 if (c
== myrpt
->p
.funcchar
)
5455 myrpt
->rem_dtmfidx
= 0;
5456 myrpt
->rem_dtmfbuf
[myrpt
->rem_dtmfidx
] = 0;
5457 time(&myrpt
->rem_dtmf_time
);
5458 rpt_mutex_unlock(&myrpt
->lock
);
5461 else if (myrpt
->rem_dtmfidx
< 0)
5463 if ((myrpt
->callmode
== 2) || (myrpt
->callmode
== 3))
5467 if (myrpt
->p
.propagate_dtmf
) do_dtmf_local(myrpt
,c
);
5468 if (myrpt
->p
.propagate_phonedtmf
) do_dtmf_phone(myrpt
,mylink
,c
);
5469 rpt_mutex_unlock(&myrpt
->lock
);
5472 else if ((c
!= myrpt
->p
.endchar
) && (myrpt
->rem_dtmfidx
>= 0))
5474 time(&myrpt
->rem_dtmf_time
);
5475 if (myrpt
->rem_dtmfidx
< MAXDTMF
)
5477 myrpt
->rem_dtmfbuf
[myrpt
->rem_dtmfidx
++] = c
;
5478 myrpt
->rem_dtmfbuf
[myrpt
->rem_dtmfidx
] = 0;
5480 rpt_mutex_unlock(&myrpt
->lock
);
5481 strncpy(cmd
, myrpt
->rem_dtmfbuf
, sizeof(cmd
) - 1);
5482 res
= collect_function_digits(myrpt
, cmd
, SOURCE_LNK
, mylink
);
5483 rpt_mutex_lock(&myrpt
->lock
);
5487 case DC_INDETERMINATE
:
5491 myrpt
->rem_dtmfidx
= 0;
5492 myrpt
->rem_dtmfbuf
[0] = 0;
5497 case DC_COMPLETEQUIET
:
5498 myrpt
->totalexecdcommands
++;
5499 myrpt
->dailyexecdcommands
++;
5500 strncpy(myrpt
->lastdtmfcommand
, cmd
, MAXDTMF
-1);
5501 myrpt
->lastdtmfcommand
[MAXDTMF
-1] = '\0';
5502 myrpt
->rem_dtmfbuf
[0] = 0;
5503 myrpt
->rem_dtmfidx
= -1;
5504 myrpt
->rem_dtmf_time
= 0;
5509 myrpt
->rem_dtmfbuf
[0] = 0;
5510 myrpt
->rem_dtmfidx
= -1;
5511 myrpt
->rem_dtmf_time
= 0;
5517 rpt_mutex_unlock(&myrpt
->lock
);
5521 static void handle_link_phone_dtmf(struct rpt
*myrpt
, struct rpt_link
*mylink
,
5528 if (myrpt
->p
.archivedir
)
5532 sprintf(str
,"DTMF(P),%s,%c",mylink
->name
,c
);
5533 donodelog(myrpt
,str
);
5535 rpt_mutex_lock(&myrpt
->lock
);
5536 if (c
== myrpt
->p
.endchar
)
5541 rpt_mutex_unlock(&myrpt
->lock
);
5545 if (myrpt
->cmdnode
[0])
5547 myrpt
->cmdnode
[0] = 0;
5548 myrpt
->dtmfidx
= -1;
5549 myrpt
->dtmfbuf
[0] = 0;
5550 rpt_mutex_unlock(&myrpt
->lock
);
5551 rpt_telemetry(myrpt
,COMPLETE
,NULL
);
5555 if (myrpt
->cmdnode
[0])
5557 rpt_mutex_unlock(&myrpt
->lock
);
5558 send_link_dtmf(myrpt
,c
);
5561 if (myrpt
->callmode
== 1)
5563 myrpt
->exten
[myrpt
->cidx
++] = c
;
5564 myrpt
->exten
[myrpt
->cidx
] = 0;
5565 /* if this exists */
5566 if (ast_exists_extension(myrpt
->pchannel
,myrpt
->patchcontext
,myrpt
->exten
,1,NULL
))
5568 myrpt
->callmode
= 2;
5569 if(!myrpt
->patchquiet
){
5570 rpt_mutex_unlock(&myrpt
->lock
);
5571 rpt_telemetry(myrpt
,PROC
,NULL
);
5572 rpt_mutex_lock(&myrpt
->lock
);
5575 /* if can continue, do so */
5576 if (!ast_canmatch_extension(myrpt
->pchannel
,myrpt
->patchcontext
,myrpt
->exten
,1,NULL
))
5578 /* call has failed, inform user */
5579 myrpt
->callmode
= 4;
5582 if ((myrpt
->callmode
== 2) || (myrpt
->callmode
== 3))
5586 if (c
== myrpt
->p
.funcchar
)
5588 myrpt
->rem_dtmfidx
= 0;
5589 myrpt
->rem_dtmfbuf
[myrpt
->rem_dtmfidx
] = 0;
5590 time(&myrpt
->rem_dtmf_time
);
5591 rpt_mutex_unlock(&myrpt
->lock
);
5594 else if ((c
!= myrpt
->p
.endchar
) && (myrpt
->rem_dtmfidx
>= 0))
5596 time(&myrpt
->rem_dtmf_time
);
5597 if (myrpt
->rem_dtmfidx
< MAXDTMF
)
5599 myrpt
->rem_dtmfbuf
[myrpt
->rem_dtmfidx
++] = c
;
5600 myrpt
->rem_dtmfbuf
[myrpt
->rem_dtmfidx
] = 0;
5602 rpt_mutex_unlock(&myrpt
->lock
);
5603 strncpy(cmd
, myrpt
->rem_dtmfbuf
, sizeof(cmd
) - 1);
5604 switch(mylink
->phonemode
)
5607 res
= collect_function_digits(myrpt
, cmd
,
5608 SOURCE_PHONE
, mylink
);
5611 res
= collect_function_digits(myrpt
, cmd
,
5612 SOURCE_DPHONE
,mylink
);
5615 res
= collect_function_digits(myrpt
, cmd
,
5616 SOURCE_LNK
, mylink
);
5620 rpt_mutex_lock(&myrpt
->lock
);
5624 case DC_INDETERMINATE
:
5632 myrpt
->rem_dtmfidx
= 0;
5633 myrpt
->rem_dtmfbuf
[0] = 0;
5638 case DC_COMPLETEQUIET
:
5639 myrpt
->totalexecdcommands
++;
5640 myrpt
->dailyexecdcommands
++;
5641 strncpy(myrpt
->lastdtmfcommand
, cmd
, MAXDTMF
-1);
5642 myrpt
->lastdtmfcommand
[MAXDTMF
-1] = '\0';
5643 myrpt
->rem_dtmfbuf
[0] = 0;
5644 myrpt
->rem_dtmfidx
= -1;
5645 myrpt
->rem_dtmf_time
= 0;
5650 myrpt
->rem_dtmfbuf
[0] = 0;
5651 myrpt
->rem_dtmfidx
= -1;
5652 myrpt
->rem_dtmf_time
= 0;
5658 rpt_mutex_unlock(&myrpt
->lock
);
5662 /* Doug Hall RBI-1 serial data definitions:
5664 * Byte 0: Expansion external outputs
5666 * Bits 0-3 are BAND as follows:
5667 * Bits 4-5 are POWER bits as follows:
5671 * Bits 6-7 are always set
5673 * Bits 0-3 MHZ in BCD format
5674 * Bits 4-5 are offset as follows:
5678 * 03 - minus minus (whatever that is)
5679 * Bit 6 is the 0/5 KHZ bit
5680 * Bit 7 is always set
5682 * Bits 0-3 are 10 KHZ in BCD format
5683 * Bits 4-7 are 100 KHZ in BCD format
5684 * Byte 4: PL Tone code and encode/decode enable bits
5685 * Bits 0-5 are PL tone code (comspec binary codes)
5686 * Bit 6 is encode enable/disable
5687 * Bit 7 is decode enable/disable
5690 /* take the frequency from the 10 mhz digits (and up) and convert it
5693 static int rbi_mhztoband(char *str
)
5697 i
= atoi(str
) / 10; /* get the 10's of mhz */
5728 /* take a PL frequency and turn it into a code */
5729 static int rbi_pltocode(char *str
)
5734 s
= strchr(str
,'.');
5736 if (s
) i
= atoi(s
+ 1);
5737 i
+= atoi(str
) * 10;
5821 * Shift out a formatted serial bit stream
5824 static void rbi_out_parallel(struct rpt
*myrpt
,unsigned char *data
)
5829 static volatile long long delayvar
;
5831 for(i
= 0 ; i
< 5 ; i
++){
5833 for(j
= 0 ; j
< 8 ; j
++){
5835 outb(d
,myrpt
->p
.iobase
);
5837 for(delayvar
= 1; delayvar
< 15000; delayvar
++);
5839 outb(d
| 2,myrpt
->p
.iobase
);
5841 for(delayvar
= 1; delayvar
< 30000; delayvar
++);
5842 outb(d
,myrpt
->p
.iobase
);
5844 for(delayvar
= 1; delayvar
< 10000; delayvar
++);
5848 for(delayvar
= 1; delayvar
< 50000; delayvar
++);
5852 static void rbi_out(struct rpt
*myrpt
,unsigned char *data
)
5854 struct zt_radio_param r
;
5856 memset(&r
,0,sizeof(struct zt_radio_param
));
5857 r
.radpar
= ZT_RADPAR_REMMODE
;
5858 r
.data
= ZT_RADPAR_REM_RBI1
;
5859 /* if setparam ioctl fails, its probably not a pciradio card */
5860 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&r
) == -1)
5862 rbi_out_parallel(myrpt
,data
);
5865 r
.radpar
= ZT_RADPAR_REMCOMMAND
;
5866 memcpy(&r
.data
,data
,5);
5867 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&r
) == -1)
5869 ast_log(LOG_WARNING
,"Cannot send RBI command for channel %s\n",myrpt
->zaprxchannel
->name
);
5874 static int serial_remote_io(struct rpt
*myrpt
, unsigned char *txbuf
, int txbytes
,
5875 unsigned char *rxbuf
, int rxmaxbytes
, int asciiflag
)
5877 int i
,j
,index
,oldmode
,olddata
;
5878 struct zt_radio_param prm
;
5882 printf("String output was: ");
5883 for(i
= 0; i
< txbytes
; i
++)
5884 printf("%02X ", (unsigned char ) txbuf
[i
]);
5887 if (myrpt
->iofd
> 0) /* if to do out a serial port */
5889 if (rxmaxbytes
&& rxbuf
) tcflush(myrpt
->iofd
,TCIFLUSH
);
5890 if (write(myrpt
->iofd
,txbuf
,txbytes
) != txbytes
) return -1;
5891 if ((!rxmaxbytes
) || (rxbuf
== NULL
)) return(0);
5892 memset(rxbuf
,0,rxmaxbytes
);
5893 for(i
= 0; i
< rxmaxbytes
; i
++)
5895 j
= read(myrpt
->iofd
,&c
,1);
5896 if (j
< 1) return(i
);
5901 if (c
== '\r') break;
5905 printf("String returned was: ");
5906 for(j
= 0; j
< i
; j
++)
5907 printf("%02X ", (unsigned char ) rxbuf
[j
]);
5913 /* if not a zap channel, cant use pciradio stuff */
5914 if (myrpt
->rxchannel
!= myrpt
->zaprxchannel
) return -1;
5916 prm
.radpar
= ZT_RADPAR_UIOMODE
;
5917 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_RADIO_GETPARAM
,&prm
) == -1) return -1;
5919 prm
.radpar
= ZT_RADPAR_UIODATA
;
5920 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_RADIO_GETPARAM
,&prm
) == -1) return -1;
5922 prm
.radpar
= ZT_RADPAR_REMMODE
;
5923 if (asciiflag
& 1) prm
.data
= ZT_RADPAR_REM_SERIAL_ASCII
;
5924 else prm
.data
= ZT_RADPAR_REM_SERIAL
;
5925 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&prm
) == -1) return -1;
5929 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_HOOK
,&i
) == -1) return -1;
5932 prm
.radpar
= ZT_RADPAR_REMCOMMAND
;
5933 prm
.data
= rxmaxbytes
;
5934 memcpy(prm
.buf
,txbuf
,txbytes
);
5935 prm
.index
= txbytes
;
5936 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&prm
) == -1) return -1;
5940 memcpy(rxbuf
,prm
.buf
,prm
.index
);
5943 prm
.radpar
= ZT_RADPAR_REMMODE
;
5944 prm
.data
= ZT_RADPAR_REM_NONE
;
5945 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&prm
) == -1) return -1;
5949 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_HOOK
,&i
) == -1) return -1;
5951 prm
.radpar
= ZT_RADPAR_UIOMODE
;
5953 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&prm
) == -1) return -1;
5954 prm
.radpar
= ZT_RADPAR_UIODATA
;
5956 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&prm
) == -1) return -1;
5960 static int civ_cmd(struct rpt
*myrpt
,unsigned char *cmd
, int cmdlen
)
5962 unsigned char rxbuf
[100];
5965 rv
= serial_remote_io(myrpt
,cmd
,cmdlen
,rxbuf
,cmdlen
+ 6,0);
5966 if (rv
== -1) return(-1);
5967 if (rv
!= (cmdlen
+ 6)) return(1);
5968 for(i
= 0; i
< 6; i
++)
5969 if (rxbuf
[i
] != cmd
[i
]) return(1);
5970 if (rxbuf
[cmdlen
] != 0xfe) return(1);
5971 if (rxbuf
[cmdlen
+ 1] != 0xfe) return(1);
5972 if (rxbuf
[cmdlen
+ 4] != 0xfb) return(1);
5973 if (rxbuf
[cmdlen
+ 5] != 0xfd) return(1);
5977 static int sendkenwood(struct rpt
*myrpt
,char *txstr
, char *rxstr
)
5981 if (debug
) printf("Send to kenwood: %s\n",txstr
);
5982 i
= serial_remote_io(myrpt
, (unsigned char *)txstr
, strlen(txstr
),
5983 (unsigned char *)rxstr
,RAD_SERIAL_BUFLEN
- 1,3);
5984 if (i
< 0) return -1;
5985 if ((i
> 0) && (rxstr
[i
- 1] == '\r'))
5987 if (debug
) printf("Got from kenwood: %s\n",rxstr
);
5991 /* take a PL frequency and turn it into a code */
5992 static int kenwood_pltocode(char *str
)
5997 s
= strchr(str
,'.');
5999 if (s
) i
= atoi(s
+ 1);
6000 i
+= atoi(str
) * 10;
6083 static int sendrxkenwood(struct rpt
*myrpt
, char *txstr
, char *rxstr
,
6088 for(i
= 0;i
< KENWOOD_RETRIES
;i
++)
6090 j
= sendkenwood(myrpt
,txstr
,rxstr
);
6091 if (j
< 0) return(j
);
6092 if (j
== 0) continue;
6093 if (!strncmp(rxstr
,cmpstr
,strlen(cmpstr
))) return(0);
6098 static int setkenwood(struct rpt
*myrpt
)
6100 char rxstr
[RAD_SERIAL_BUFLEN
],txstr
[RAD_SERIAL_BUFLEN
],freq
[20];
6101 char mhz
[MAXREMSTR
],offset
[20],band
,decimals
[MAXREMSTR
],band1
,band2
;
6103 int offsets
[] = {0,2,1};
6104 int powers
[] = {2,1,0};
6106 if (sendrxkenwood(myrpt
,"VMC 0,0\r",rxstr
,"VMC") < 0) return -1;
6107 split_freq(mhz
, decimals
, myrpt
->freq
);
6108 if (atoi(mhz
) > 400)
6113 strcpy(offset
,"005000000");
6120 strcpy(offset
,"000600000");
6122 strcpy(freq
,"000000");
6123 strncpy(freq
,decimals
,strlen(decimals
));
6124 sprintf(txstr
,"VW %c,%05d%s,0,%d,0,%d,%d,,%02d,,%02d,%s\r",
6125 band
,atoi(mhz
),freq
,offsets
[(int)myrpt
->offset
],
6126 (myrpt
->txplon
!= 0),(myrpt
->rxplon
!= 0),
6127 kenwood_pltocode(myrpt
->txpl
),kenwood_pltocode(myrpt
->rxpl
),
6129 if (sendrxkenwood(myrpt
,txstr
,rxstr
,"VW") < 0) return -1;
6130 sprintf(txstr
,"RBN %c\r",band2
);
6131 if (sendrxkenwood(myrpt
,txstr
,rxstr
,"RBN") < 0) return -1;
6132 sprintf(txstr
,"PC %c,%d\r",band1
,powers
[(int)myrpt
->powerlevel
]);
6133 if (sendrxkenwood(myrpt
,txstr
,rxstr
,"PC") < 0) return -1;
6137 static int setrbi(struct rpt
*myrpt
)
6139 char tmp
[MAXREMSTR
] = "",*s
;
6140 unsigned char rbicmd
[5];
6141 int band
,txoffset
= 0,txpower
= 0,rxpl
;
6143 /* must be a remote system */
6144 if (!myrpt
->remote
) return(0);
6145 /* must have rbi hardware */
6146 if (strncmp(myrpt
->remote
,remote_rig_rbi
,3)) return(0);
6147 if (setrbi_check(myrpt
) == -1) return(-1);
6148 strncpy(tmp
, myrpt
->freq
, sizeof(tmp
) - 1);
6149 s
= strchr(tmp
,'.');
6150 /* if no decimal, is invalid */
6154 printf("@@@@ Frequency needs a decimal\n");
6159 if (strlen(tmp
) < 2){
6161 printf("@@@@ Bad MHz digits: %s\n", tmp
);
6167 printf("@@@@ Bad KHz digits: %s\n", s
);
6171 if ((s
[2] != '0') && (s
[2] != '5')){
6173 printf("@@@@ KHz must end in 0 or 5: %c\n", s
[2]);
6177 band
= rbi_mhztoband(tmp
);
6180 printf("@@@@ Bad Band: %s\n", tmp
);
6184 rxpl
= rbi_pltocode(myrpt
->rxpl
);
6188 printf("@@@@ Bad TX PL: %s\n", myrpt
->rxpl
);
6193 switch(myrpt
->offset
)
6205 switch(myrpt
->powerlevel
)
6218 rbicmd
[1] = band
| txpower
| 0xc0;
6219 rbicmd
[2] = (*(s
- 2) - '0') | txoffset
| 0x80;
6220 if (s
[2] == '5') rbicmd
[2] |= 0x40;
6221 rbicmd
[3] = ((*s
- '0') << 4) + (s
[1] - '0');
6223 if (myrpt
->txplon
) rbicmd
[4] |= 0x40;
6224 if (myrpt
->rxplon
) rbicmd
[4] |= 0x80;
6225 rbi_out(myrpt
,rbicmd
);
6229 static int setrbi_check(struct rpt
*myrpt
)
6231 char tmp
[MAXREMSTR
] = "",*s
;
6234 /* must be a remote system */
6235 if (!myrpt
->remote
) return(0);
6236 /* must have rbi hardware */
6237 if (strncmp(myrpt
->remote
,remote_rig_rbi
,3)) return(0);
6238 strncpy(tmp
, myrpt
->freq
, sizeof(tmp
) - 1);
6239 s
= strchr(tmp
,'.');
6240 /* if no decimal, is invalid */
6244 printf("@@@@ Frequency needs a decimal\n");
6249 if (strlen(tmp
) < 2){
6251 printf("@@@@ Bad MHz digits: %s\n", tmp
);
6257 printf("@@@@ Bad KHz digits: %s\n", s
);
6261 if ((s
[2] != '0') && (s
[2] != '5')){
6263 printf("@@@@ KHz must end in 0 or 5: %c\n", s
[2]);
6267 band
= rbi_mhztoband(tmp
);
6270 printf("@@@@ Bad Band: %s\n", tmp
);
6274 txpl
= rbi_pltocode(myrpt
->txpl
);
6278 printf("@@@@ Bad TX PL: %s\n", myrpt
->txpl
);
6284 static int check_freq_kenwood(int m
, int d
, int *defmode
)
6286 int dflmd
= REM_MODE_FM
;
6288 if (m
== 144){ /* 2 meters */
6292 else if((m
>= 145) && (m
< 148)){
6295 else if((m
>= 430) && (m
< 450)){ /* 70 centimeters */
6309 /* Check for valid rbi frequency */
6310 /* Hard coded limits now, configurable later, maybe? */
6312 static int check_freq_rbi(int m
, int d
, int *defmode
)
6314 int dflmd
= REM_MODE_FM
;
6316 if(m
== 50){ /* 6 meters */
6320 else if((m
>= 51) && ( m
< 54)){
6323 else if(m
== 144){ /* 2 meters */
6327 else if((m
>= 145) && (m
< 148)){
6330 else if((m
>= 222) && (m
< 225)){ /* 1.25 meters */
6333 else if((m
>= 430) && (m
< 450)){ /* 70 centimeters */
6336 else if((m
>= 1240) && (m
< 1300)){ /* 23 centimeters */
6350 * Convert decimals of frequency to int
6353 static int decimals2int(char *fraction
)
6356 char len
= strlen(fraction
);
6357 int multiplier
= 100000;
6362 for( i
= 0 ; i
< len
; i
++, multiplier
/= 10)
6363 res
+= (fraction
[i
] - '0') * multiplier
;
6369 * Split frequency into mhz and decimals
6372 static int split_freq(char *mhz
, char *decimals
, char *freq
)
6374 char freq_copy
[MAXREMSTR
];
6377 decp
= strchr(strncpy(freq_copy
, freq
, MAXREMSTR
),'.');
6380 strncpy(mhz
, freq_copy
, MAXREMSTR
);
6381 strcpy(decimals
, "00000");
6382 strncpy(decimals
, decp
, strlen(decp
));
6392 * Split ctcss frequency into hertz and decimal
6395 static int split_ctcss_freq(char *hertz
, char *decimal
, char *freq
)
6397 char freq_copy
[MAXREMSTR
];
6400 decp
= strchr(strncpy(freq_copy
, freq
, MAXREMSTR
),'.');
6403 strncpy(hertz
, freq_copy
, MAXREMSTR
);
6404 strncpy(decimal
, decp
, strlen(decp
));
6405 decimal
[strlen(decp
)] = '\0';
6415 * FT-897 I/O handlers
6418 /* Check to see that the frequency is valid */
6419 /* Hard coded limits now, configurable later, maybe? */
6422 static int check_freq_ft897(int m
, int d
, int *defmode
)
6424 int dflmd
= REM_MODE_FM
;
6426 if(m
== 1){ /* 160 meters */
6427 dflmd
= REM_MODE_LSB
;
6431 else if(m
== 3){ /* 80 meters */
6432 dflmd
= REM_MODE_LSB
;
6436 else if(m
== 7){ /* 40 meters */
6437 dflmd
= REM_MODE_LSB
;
6441 else if(m
== 14){ /* 20 meters */
6442 dflmd
= REM_MODE_USB
;
6446 else if(m
== 18){ /* 17 meters */
6447 dflmd
= REM_MODE_USB
;
6448 if((d
< 6800) || (d
> 16800))
6451 else if(m
== 21){ /* 15 meters */
6452 dflmd
= REM_MODE_USB
;
6453 if((d
< 20000) || (d
> 45000))
6456 else if(m
== 24){ /* 12 meters */
6457 dflmd
= REM_MODE_USB
;
6458 if((d
< 89000) || (d
> 99000))
6461 else if(m
== 28){ /* 10 meters */
6462 dflmd
= REM_MODE_USB
;
6466 dflmd
= REM_MODE_FM
;
6468 dflmd
= REM_MODE_USB
;
6472 else if(m
== 50){ /* 6 meters */
6474 dflmd
= REM_MODE_FM
;
6476 dflmd
= REM_MODE_USB
;
6479 else if((m
>= 51) && ( m
< 54)){
6480 dflmd
= REM_MODE_FM
;
6482 else if(m
== 144){ /* 2 meters */
6484 dflmd
= REM_MODE_FM
;
6486 dflmd
= REM_MODE_USB
;
6488 else if((m
>= 145) && (m
< 148)){
6489 dflmd
= REM_MODE_FM
;
6491 else if((m
>= 430) && (m
< 450)){ /* 70 centimeters */
6493 dflmd
= REM_MODE_USB
;
6495 dflmd
= REM_MODE_FM
;
6508 * Set a new frequency for the FT897
6511 static int set_freq_ft897(struct rpt
*myrpt
, char *newfreq
)
6513 unsigned char cmdstr
[5];
6515 char mhz
[MAXREMSTR
];
6516 char decimals
[MAXREMSTR
];
6520 printf("New frequency: %s\n",newfreq
);
6522 if(split_freq(mhz
, decimals
, newfreq
))
6528 /* The FT-897 likes packed BCD frequencies */
6530 cmdstr
[0] = ((m
/ 100) << 4) + ((m
% 100)/10); /* 100MHz 10Mhz */
6531 cmdstr
[1] = ((m
% 10) << 4) + (d
/ 10000); /* 1MHz 100KHz */
6532 cmdstr
[2] = (((d
% 10000)/1000) << 4) + ((d
% 1000)/ 100); /* 10KHz 1KHz */
6533 cmdstr
[3] = (((d
% 100)/10) << 4) + (d
% 10); /* 100Hz 10Hz */
6534 cmdstr
[4] = 0x01; /* command */
6536 return serial_remote_io(myrpt
, cmdstr
, 5, NULL
, 0, 0);
6540 /* ft-897 simple commands */
6542 static int simple_command_ft897(struct rpt
*myrpt
, char command
)
6544 unsigned char cmdstr
[5];
6546 memset(cmdstr
, 0, 5);
6548 cmdstr
[4] = command
;
6550 return serial_remote_io(myrpt
, cmdstr
, 5, NULL
, 0, 0);
6556 static int set_offset_ft897(struct rpt
*myrpt
, char offset
)
6558 unsigned char cmdstr
[5];
6560 memset(cmdstr
, 0, 5);
6581 return serial_remote_io(myrpt
, cmdstr
, 5, NULL
, 0, 0);
6586 static int set_mode_ft897(struct rpt
*myrpt
, char newmode
)
6588 unsigned char cmdstr
[5];
6590 memset(cmdstr
, 0, 5);
6614 return serial_remote_io(myrpt
, cmdstr
, 5, NULL
, 0, 0);
6617 /* Set tone encode and decode modes */
6619 static int set_ctcss_mode_ft897(struct rpt
*myrpt
, char txplon
, char rxplon
)
6621 unsigned char cmdstr
[5];
6623 memset(cmdstr
, 0, 5);
6625 if(rxplon
&& txplon
)
6626 cmdstr
[0] = 0x2A; /* Encode and Decode */
6627 else if (!rxplon
&& txplon
)
6628 cmdstr
[0] = 0x4A; /* Encode only */
6629 else if (rxplon
&& !txplon
)
6630 cmdstr
[0] = 0x3A; /* Encode only */
6632 cmdstr
[0] = 0x8A; /* OFF */
6636 return serial_remote_io(myrpt
, cmdstr
, 5, NULL
, 0, 0);
6640 /* Set transmit and receive ctcss tone frequencies */
6642 static int set_ctcss_freq_ft897(struct rpt
*myrpt
, char *txtone
, char *rxtone
)
6644 unsigned char cmdstr
[5];
6645 char hertz
[MAXREMSTR
],decimal
[MAXREMSTR
];
6648 memset(cmdstr
, 0, 5);
6650 if(split_ctcss_freq(hertz
, decimal
, txtone
))
6656 cmdstr
[0] = ((h
/ 100) << 4) + (h
% 100)/ 10;
6657 cmdstr
[1] = ((h
% 10) << 4) + (d
% 10);
6661 if(split_ctcss_freq(hertz
, decimal
, rxtone
))
6667 cmdstr
[2] = ((h
/ 100) << 4) + (h
% 100)/ 10;
6668 cmdstr
[3] = ((h
% 10) << 4) + (d
% 10);
6672 return serial_remote_io(myrpt
, cmdstr
, 5, NULL
, 0, 0);
6677 static int set_ft897(struct rpt
*myrpt
)
6682 printf("@@@@ lock on\n");
6684 res
= simple_command_ft897(myrpt
, 0x00); /* LOCK on */
6687 printf("@@@@ ptt off\n");
6690 res
= simple_command_ft897(myrpt
, 0x88); /* PTT off */
6693 printf("Modulation mode\n");
6696 res
= set_mode_ft897(myrpt
, myrpt
->remmode
); /* Modulation mode */
6699 printf("Split off\n");
6702 simple_command_ft897(myrpt
, 0x82); /* Split off */
6705 printf("Frequency\n");
6708 res
= set_freq_ft897(myrpt
, myrpt
->freq
); /* Frequency */
6709 if((myrpt
->remmode
== REM_MODE_FM
)){
6713 res
= set_offset_ft897(myrpt
, myrpt
->offset
); /* Offset if FM */
6714 if((!res
)&&(myrpt
->rxplon
|| myrpt
->txplon
)){
6716 printf("CTCSS tone freqs.\n");
6717 res
= set_ctcss_freq_ft897(myrpt
, myrpt
->txpl
, myrpt
->rxpl
); /* CTCSS freqs if CTCSS is enabled */
6721 printf("CTCSS mode\n");
6722 res
= set_ctcss_mode_ft897(myrpt
, myrpt
->txplon
, myrpt
->rxplon
); /* CTCSS mode */
6725 if((myrpt
->remmode
== REM_MODE_USB
)||(myrpt
->remmode
== REM_MODE_LSB
)){
6727 printf("Clarifier off\n");
6728 simple_command_ft897(myrpt
, 0x85); /* Clarifier off if LSB or USB */
6733 static int closerem_ft897(struct rpt
*myrpt
)
6735 simple_command_ft897(myrpt
, 0x88); /* PTT off */
6740 * Bump frequency up or down by a small amount
6741 * Return 0 if the new frequnecy is valid, or -1 if invalid
6742 * Interval is in Hz, resolution is 10Hz
6745 static int multimode_bump_freq_ft897(struct rpt
*myrpt
, int interval
)
6748 char mhz
[MAXREMSTR
], decimals
[MAXREMSTR
];
6751 printf("Before bump: %s\n", myrpt
->freq
);
6753 if(split_freq(mhz
, decimals
, myrpt
->freq
))
6759 d
+= (interval
/ 10); /* 10Hz resolution */
6764 else if(d
>= 100000){
6769 if(check_freq_ft897(m
, d
, NULL
)){
6771 printf("Bump freq invalid\n");
6775 snprintf(myrpt
->freq
, MAXREMSTR
, "%d.%05d", m
, d
);
6778 printf("After bump: %s\n", myrpt
->freq
);
6780 return set_freq_ft897(myrpt
, myrpt
->freq
);
6786 * IC-706 I/O handlers
6789 /* Check to see that the frequency is valid */
6790 /* Hard coded limits now, configurable later, maybe? */
6793 static int check_freq_ic706(int m
, int d
, int *defmode
)
6795 int dflmd
= REM_MODE_FM
;
6797 if(m
== 1){ /* 160 meters */
6798 dflmd
= REM_MODE_LSB
;
6802 else if(m
== 3){ /* 80 meters */
6803 dflmd
= REM_MODE_LSB
;
6807 else if(m
== 7){ /* 40 meters */
6808 dflmd
= REM_MODE_LSB
;
6812 else if(m
== 14){ /* 20 meters */
6813 dflmd
= REM_MODE_USB
;
6817 else if(m
== 18){ /* 17 meters */
6818 dflmd
= REM_MODE_USB
;
6819 if((d
< 6800) || (d
> 16800))
6822 else if(m
== 21){ /* 15 meters */
6823 dflmd
= REM_MODE_USB
;
6824 if((d
< 20000) || (d
> 45000))
6827 else if(m
== 24){ /* 12 meters */
6828 dflmd
= REM_MODE_USB
;
6829 if((d
< 89000) || (d
> 99000))
6832 else if(m
== 28){ /* 10 meters */
6833 dflmd
= REM_MODE_USB
;
6837 dflmd
= REM_MODE_FM
;
6839 dflmd
= REM_MODE_USB
;
6843 else if(m
== 50){ /* 6 meters */
6845 dflmd
= REM_MODE_FM
;
6847 dflmd
= REM_MODE_USB
;
6850 else if((m
>= 51) && ( m
< 54)){
6851 dflmd
= REM_MODE_FM
;
6853 else if(m
== 144){ /* 2 meters */
6855 dflmd
= REM_MODE_FM
;
6857 dflmd
= REM_MODE_USB
;
6859 else if((m
>= 145) && (m
< 148)){
6860 dflmd
= REM_MODE_FM
;
6862 else if((m
>= 430) && (m
< 450)){ /* 70 centimeters */
6864 dflmd
= REM_MODE_USB
;
6866 dflmd
= REM_MODE_FM
;
6878 /* take a PL frequency and turn it into a code */
6879 static int ic706_pltocode(char *str
)
6884 s
= strchr(str
,'.');
6886 if (s
) i
= atoi(s
+ 1);
6887 i
+= atoi(str
) * 10;
6994 /* ic-706 simple commands */
6996 static int simple_command_ic706(struct rpt
*myrpt
, char command
, char subcommand
)
6998 unsigned char cmdstr
[10];
7000 cmdstr
[0] = cmdstr
[1] = 0xfe;
7001 cmdstr
[2] = myrpt
->p
.civaddr
;
7003 cmdstr
[4] = command
;
7004 cmdstr
[5] = subcommand
;
7007 return(civ_cmd(myrpt
,cmdstr
,7));
7011 * Set a new frequency for the ic706
7014 static int set_freq_ic706(struct rpt
*myrpt
, char *newfreq
)
7016 unsigned char cmdstr
[20];
7017 char mhz
[MAXREMSTR
], decimals
[MAXREMSTR
];
7022 printf("New frequency: %s\n",newfreq
);
7024 if(split_freq(mhz
, decimals
, newfreq
))
7030 /* The ic-706 likes packed BCD frequencies */
7032 cmdstr
[0] = cmdstr
[1] = 0xfe;
7033 cmdstr
[2] = myrpt
->p
.civaddr
;
7036 cmdstr
[5] = ((d
% 10) << 4);
7037 cmdstr
[6] = (((d
% 1000)/ 100) << 4) + ((d
% 100)/10);
7038 cmdstr
[7] = ((d
/ 10000) << 4) + ((d
% 10000)/1000);
7039 cmdstr
[8] = (((m
% 100)/10) << 4) + (m
% 10);
7040 cmdstr
[9] = (m
/ 100);
7043 return(civ_cmd(myrpt
,cmdstr
,11));
7048 static int set_offset_ic706(struct rpt
*myrpt
, char offset
)
7069 return simple_command_ic706(myrpt
,0x0f,c
);
7075 static int set_mode_ic706(struct rpt
*myrpt
, char newmode
)
7099 return simple_command_ic706(myrpt
,6,c
);
7102 /* Set tone encode and decode modes */
7104 static int set_ctcss_mode_ic706(struct rpt
*myrpt
, char txplon
, char rxplon
)
7106 unsigned char cmdstr
[10];
7109 cmdstr
[0] = cmdstr
[1] = 0xfe;
7110 cmdstr
[2] = myrpt
->p
.civaddr
;
7114 cmdstr
[6] = (txplon
!= 0);
7117 rv
= civ_cmd(myrpt
,cmdstr
,8);
7120 cmdstr
[0] = cmdstr
[1] = 0xfe;
7121 cmdstr
[2] = myrpt
->p
.civaddr
;
7125 cmdstr
[6] = (rxplon
!= 0);
7128 return(civ_cmd(myrpt
,cmdstr
,8));
7132 /* Set transmit and receive ctcss tone frequencies */
7134 static int set_ctcss_freq_ic706(struct rpt
*myrpt
, char *txtone
, char *rxtone
)
7136 unsigned char cmdstr
[10];
7137 char hertz
[MAXREMSTR
],decimal
[MAXREMSTR
];
7140 memset(cmdstr
, 0, 5);
7142 if(split_ctcss_freq(hertz
, decimal
, txtone
))
7148 cmdstr
[0] = cmdstr
[1] = 0xfe;
7149 cmdstr
[2] = myrpt
->p
.civaddr
;
7153 cmdstr
[6] = ((h
/ 100) << 4) + (h
% 100)/ 10;
7154 cmdstr
[7] = ((h
% 10) << 4) + (d
% 10);
7157 rv
= civ_cmd(myrpt
,cmdstr
,9);
7160 if (!rxtone
) return(0);
7162 if(split_ctcss_freq(hertz
, decimal
, rxtone
))
7168 cmdstr
[0] = cmdstr
[1] = 0xfe;
7169 cmdstr
[2] = myrpt
->p
.civaddr
;
7173 cmdstr
[6] = ((h
/ 100) << 4) + (h
% 100)/ 10;
7174 cmdstr
[7] = ((h
% 10) << 4) + (d
% 10);
7176 return(civ_cmd(myrpt
,cmdstr
,9));
7180 static int vfo_ic706(struct rpt
*myrpt
)
7182 unsigned char cmdstr
[10];
7184 cmdstr
[0] = cmdstr
[1] = 0xfe;
7185 cmdstr
[2] = myrpt
->p
.civaddr
;
7190 return(civ_cmd(myrpt
,cmdstr
,6));
7193 static int mem2vfo_ic706(struct rpt
*myrpt
)
7195 unsigned char cmdstr
[10];
7197 cmdstr
[0] = cmdstr
[1] = 0xfe;
7198 cmdstr
[2] = myrpt
->p
.civaddr
;
7203 return(civ_cmd(myrpt
,cmdstr
,6));
7206 static int select_mem_ic706(struct rpt
*myrpt
, int slot
)
7208 unsigned char cmdstr
[10];
7210 cmdstr
[0] = cmdstr
[1] = 0xfe;
7211 cmdstr
[2] = myrpt
->p
.civaddr
;
7215 cmdstr
[6] = ((slot
/ 10) << 4) + (slot
% 10);
7218 return(civ_cmd(myrpt
,cmdstr
,8));
7221 static int set_ic706(struct rpt
*myrpt
)
7226 printf("Set to VFO A\n");
7229 res
= simple_command_ic706(myrpt
,7,0);
7232 if((myrpt
->remmode
== REM_MODE_FM
))
7234 i
= ic706_pltocode(myrpt
->rxpl
);
7235 if (i
== -1) return -1;
7237 printf("Select memory number\n");
7239 res
= select_mem_ic706(myrpt
,i
+ IC706_PL_MEMORY_OFFSET
);
7241 printf("Transfer memory to VFO\n");
7243 res
= mem2vfo_ic706(myrpt
);
7247 printf("Set to VFO\n");
7250 res
= vfo_ic706(myrpt
);
7253 printf("Modulation mode\n");
7256 res
= set_mode_ic706(myrpt
, myrpt
->remmode
); /* Modulation mode */
7259 printf("Split off\n");
7262 simple_command_ic706(myrpt
, 0x82,0); /* Split off */
7265 printf("Frequency\n");
7268 res
= set_freq_ic706(myrpt
, myrpt
->freq
); /* Frequency */
7269 if((myrpt
->remmode
== REM_MODE_FM
)){
7273 res
= set_offset_ic706(myrpt
, myrpt
->offset
); /* Offset if FM */
7276 printf("CTCSS mode\n");
7277 res
= set_ctcss_mode_ic706(myrpt
, myrpt
->txplon
, myrpt
->rxplon
); /* CTCSS mode */
7284 * Bump frequency up or down by a small amount
7285 * Return 0 if the new frequnecy is valid, or -1 if invalid
7286 * Interval is in Hz, resolution is 10Hz
7289 static int multimode_bump_freq_ic706(struct rpt
*myrpt
, int interval
)
7292 char mhz
[MAXREMSTR
], decimals
[MAXREMSTR
];
7293 unsigned char cmdstr
[20];
7296 printf("Before bump: %s\n", myrpt
->freq
);
7298 if(split_freq(mhz
, decimals
, myrpt
->freq
))
7304 d
+= (interval
/ 10); /* 10Hz resolution */
7309 else if(d
>= 100000){
7314 if(check_freq_ic706(m
, d
, NULL
)){
7316 printf("Bump freq invalid\n");
7320 snprintf(myrpt
->freq
, MAXREMSTR
, "%d.%05d", m
, d
);
7323 printf("After bump: %s\n", myrpt
->freq
);
7325 /* The ic-706 likes packed BCD frequencies */
7327 cmdstr
[0] = cmdstr
[1] = 0xfe;
7328 cmdstr
[2] = myrpt
->p
.civaddr
;
7331 cmdstr
[5] = ((d
% 10) << 4);
7332 cmdstr
[6] = (((d
% 1000)/ 100) << 4) + ((d
% 100)/10);
7333 cmdstr
[7] = ((d
/ 10000) << 4) + ((d
% 10000)/1000);
7334 cmdstr
[8] = (((m
% 100)/10) << 4) + (m
% 10);
7335 cmdstr
[9] = (m
/ 100);
7338 return(serial_remote_io(myrpt
,cmdstr
,11,NULL
,0,0));
7344 * Dispatch to correct I/O handler
7347 static int setrem(struct rpt
*myrpt
)
7350 char *offsets
[] = {"MINUS","SIMPLEX","PLUS"};
7351 char *powerlevels
[] = {"LOW","MEDIUM","HIGH"};
7352 char *modes
[] = {"FM","USB","LSB","AM"};
7355 if (myrpt
->p
.archivedir
)
7357 sprintf(str
,"FREQ,%s,%s,%s,%s,%s,%s,%d,%d",myrpt
->freq
,
7358 modes
[(int)myrpt
->remmode
],
7359 myrpt
->txpl
,myrpt
->rxpl
,offsets
[(int)myrpt
->offset
],
7360 powerlevels
[(int)myrpt
->powerlevel
],myrpt
->txplon
,
7362 donodelog(myrpt
,str
);
7364 if(!strcmp(myrpt
->remote
, remote_rig_ft897
))
7366 rpt_telemetry(myrpt
,SETREMOTE
,NULL
);
7369 if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
7371 rpt_telemetry(myrpt
,SETREMOTE
,NULL
);
7374 else if(!strcmp(myrpt
->remote
, remote_rig_rbi
))
7376 res
= setrbi_check(myrpt
);
7379 rpt_telemetry(myrpt
,SETREMOTE
,NULL
);
7383 else if(!strcmp(myrpt
->remote
, remote_rig_kenwood
)) {
7384 rpt_telemetry(myrpt
,SETREMOTE
,NULL
);
7390 if (res
< 0) ast_log(LOG_ERROR
,"Unable to send remote command on node %s\n",myrpt
->name
);
7395 static int closerem(struct rpt
*myrpt
)
7397 if(!strcmp(myrpt
->remote
, remote_rig_ft897
))
7398 return closerem_ft897(myrpt
);
7404 * Dispatch to correct RX frequency checker
7407 static int check_freq(struct rpt
*myrpt
, int m
, int d
, int *defmode
)
7409 if(!strcmp(myrpt
->remote
, remote_rig_ft897
))
7410 return check_freq_ft897(m
, d
, defmode
);
7411 else if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
7412 return check_freq_ic706(m
, d
, defmode
);
7413 else if(!strcmp(myrpt
->remote
, remote_rig_rbi
))
7414 return check_freq_rbi(m
, d
, defmode
);
7415 else if(!strcmp(myrpt
->remote
, remote_rig_kenwood
))
7416 return check_freq_kenwood(m
, d
, defmode
);
7422 * Check TX frequency before transmitting
7425 static char check_tx_freq(struct rpt
*myrpt
)
7428 int radio_mhz
, radio_decimals
, ulimit_mhz
, ulimit_decimals
, llimit_mhz
, llimit_decimals
;
7429 char radio_mhz_char
[MAXREMSTR
];
7430 char radio_decimals_char
[MAXREMSTR
];
7431 char limit_mhz_char
[MAXREMSTR
];
7432 char limit_decimals_char
[MAXREMSTR
];
7434 char *limit_ranges
[40];
7435 struct ast_variable
*limitlist
;
7438 /* Must have user logged in and tx_limits defined */
7440 if(!myrpt
->p
.txlimitsstanzaname
|| !myrpt
->loginuser
[0] || !myrpt
->loginlevel
[0]){
7442 ast_log(LOG_NOTICE
, "No tx band table defined, or no user logged in\n");
7444 return 1; /* Assume it's ok otherwise */
7447 /* Retrieve the band table for the loginlevel */
7448 limitlist
= ast_variable_browse(myrpt
->cfg
, myrpt
->p
.txlimitsstanzaname
);
7451 ast_log(LOG_WARNING
, "No entries in %s band table stanza\n", myrpt
->p
.txlimitsstanzaname
);
7455 split_freq(radio_mhz_char
, radio_decimals_char
, myrpt
->freq
);
7456 radio_mhz
= atoi(radio_mhz_char
);
7457 radio_decimals
= decimals2int(radio_decimals_char
);
7461 ast_log(LOG_NOTICE
, "Login User = %s, login level = %s\n", myrpt
->loginuser
, myrpt
->loginlevel
);
7464 /* Find our entry */
7466 for(;limitlist
; limitlist
=limitlist
->next
){
7467 if(!strcmp(limitlist
->name
, myrpt
->loginlevel
))
7472 ast_log(LOG_WARNING
, "Can't find %s entry in band table stanza %s\n", myrpt
->loginlevel
, myrpt
->p
.txlimitsstanzaname
);
7477 ast_log(LOG_NOTICE
, "Auth %s = %s\n", limitlist
->name
, limitlist
->value
);
7480 /* Parse the limits */
7482 strncpy(limits
, limitlist
->value
, 256);
7484 finddelim(limits
, limit_ranges
, 40);
7485 for(i
= 0; i
< 40 && limit_ranges
[i
] ; i
++){
7488 strncpy(range
, limit_ranges
[i
], 40);
7491 ast_log(LOG_NOTICE
, "Checking to see if %s is within limits of %s\n", myrpt
->freq
, range
);
7494 r
= strchr(range
, '-');
7496 ast_log(LOG_WARNING
, "Malformed range in %s tx band table entry\n", limitlist
->name
);
7500 s
= eatwhite(range
);
7502 split_freq(limit_mhz_char
, limit_decimals_char
, s
);
7503 llimit_mhz
= atoi(limit_mhz_char
);
7504 llimit_decimals
= decimals2int(limit_decimals_char
);
7505 split_freq(limit_mhz_char
, limit_decimals_char
, r
);
7506 ulimit_mhz
= atoi(limit_mhz_char
);
7507 ulimit_decimals
= decimals2int(limit_decimals_char
);
7509 if((radio_mhz
>= llimit_mhz
) && (radio_mhz
<= ulimit_mhz
)){
7510 if(radio_mhz
== llimit_mhz
){ /* CASE 1: TX freq is in llimit mhz portion of band */
7511 if(radio_decimals
>= llimit_decimals
){ /* Cannot be below llimit decimals */
7512 if(llimit_mhz
== ulimit_mhz
){ /* If bandwidth < 1Mhz, check ulimit decimals */
7513 if(radio_decimals
<= ulimit_decimals
){
7518 ast_log(LOG_NOTICE
, "Invalid TX frequency, debug msg 1\n");
7526 else{ /* Is below llimit decimals */
7528 ast_log(LOG_NOTICE
, "Invalid TX frequency, debug msg 2\n");
7532 else if(radio_mhz
== ulimit_mhz
){ /* CASE 2: TX freq not in llimit mhz portion of band */
7533 if(radio_decimals
<= ulimit_decimals
){
7536 else{ /* Is above ulimit decimals */
7538 ast_log(LOG_NOTICE
, "Invalid TX frequency, debug msg 3\n");
7542 else /* CASE 3: TX freq within a multi-Mhz band and ok */
7546 if(debug
> 3) /* No match found in TX band table */
7547 ast_log(LOG_NOTICE
, "Invalid TX frequency, debug msg 4\n");
7553 * Dispatch to correct frequency bumping function
7556 static int multimode_bump_freq(struct rpt
*myrpt
, int interval
)
7558 if(!strcmp(myrpt
->remote
, remote_rig_ft897
))
7559 return multimode_bump_freq_ft897(myrpt
, interval
);
7560 else if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
7561 return multimode_bump_freq_ic706(myrpt
, interval
);
7568 * Queue announcment that scan has been stopped
7571 static void stop_scan(struct rpt
*myrpt
)
7573 myrpt
->hfscanstop
= 1;
7574 rpt_telemetry(myrpt
,SCAN
,0);
7578 * This is called periodically when in scan mode
7582 static int service_scan(struct rpt
*myrpt
)
7585 char mhz
[MAXREMSTR
], decimals
[MAXREMSTR
], k10
=0i
, k100
=0;
7587 switch(myrpt
->hfscanmode
){
7589 case HF_SCAN_DOWN_SLOW
:
7590 interval
= -10; /* 100Hz /sec */
7593 case HF_SCAN_DOWN_QUICK
:
7594 interval
= -50; /* 500Hz /sec */
7597 case HF_SCAN_DOWN_FAST
:
7598 interval
= -200; /* 2KHz /sec */
7601 case HF_SCAN_UP_SLOW
:
7602 interval
= 10; /* 100Hz /sec */
7605 case HF_SCAN_UP_QUICK
:
7606 interval
= 50; /* 500 Hz/sec */
7609 case HF_SCAN_UP_FAST
:
7610 interval
= 200; /* 2KHz /sec */
7614 myrpt
->hfscanmode
= 0; /* Huh? */
7618 res
= split_freq(mhz
, decimals
, myrpt
->freq
);
7623 res
= multimode_bump_freq(myrpt
, interval
);
7627 res
= split_freq(mhz
, decimals
, myrpt
->freq
);
7631 myrpt
->hfscanmode
= 0;
7632 myrpt
->hfscanstatus
= -2;
7636 /* Announce 10KHz boundaries */
7637 if(k10
!= decimals
[1]){
7638 int myhund
= (interval
< 0) ? k100
: decimals
[0];
7639 int myten
= (interval
< 0) ? k10
: decimals
[1];
7640 myrpt
->hfscanstatus
= (myten
== '0') ? (myhund
- '0') * 100 : (myten
- '0') * 10;
7641 } else myrpt
->hfscanstatus
= 0;
7647 * Retrieve a memory channel
7648 * Return 0 if sucessful,
7649 * -1 if channel not found,
7653 static int retreive_memory(struct rpt
*myrpt
, char *memory
)
7655 char tmp
[30], *s
, *s1
, *val
;
7657 val
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->p
.memory
, memory
);
7661 strncpy(tmp
,val
,sizeof(tmp
) - 1);
7662 tmp
[sizeof(tmp
)-1] = 0;
7664 s
= strchr(tmp
,',');
7672 strncpy(myrpt
->freq
, tmp
, sizeof(myrpt
->freq
) - 1);
7673 strncpy(myrpt
->rxpl
, s
, sizeof(myrpt
->rxpl
) - 1);
7674 strncpy(myrpt
->txpl
, s
, sizeof(myrpt
->rxpl
) - 1);
7675 myrpt
->remmode
= REM_MODE_FM
;
7676 myrpt
->offset
= REM_SIMPLEX
;
7677 myrpt
->powerlevel
= REM_MEDPWR
;
7678 myrpt
->txplon
= myrpt
->rxplon
= 0;
7683 strcpy(myrpt
->rxpl
, "100.0");
7684 strcpy(myrpt
->txpl
, "100.0");
7685 myrpt
->remmode
= REM_MODE_AM
;
7689 strcpy(myrpt
->rxpl
, "100.0");
7690 strcpy(myrpt
->txpl
, "100.0");
7691 myrpt
->remmode
= REM_MODE_LSB
;
7694 myrpt
->remmode
= REM_MODE_FM
;
7698 myrpt
->powerlevel
= REM_LOWPWR
;
7702 myrpt
->powerlevel
= REM_HIPWR
;
7707 myrpt
->powerlevel
= REM_MEDPWR
;
7711 myrpt
->offset
= REM_MINUS
;
7715 myrpt
->offset
= REM_PLUS
;
7720 myrpt
->offset
= REM_SIMPLEX
;
7735 strcpy(myrpt
->rxpl
, "100.0");
7736 strcpy(myrpt
->txpl
, "100.0");
7737 myrpt
->remmode
= REM_MODE_USB
;
7749 * Remote base function
7752 static int function_remote(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
7755 int i
,j
,p
,r
,ht
,k
,l
,ls2
,m
,d
,offset
,offsave
, modesave
, defmode
;
7757 char oc
,*cp
,*cp1
,*cp2
;
7758 char tmp
[20], freq
[20] = "", savestr
[20] = "";
7759 char mhz
[MAXREMSTR
], decimals
[MAXREMSTR
];
7761 if((!param
) || (command_source
== SOURCE_RPT
) || (command_source
== SOURCE_LNK
))
7766 if ((p
!= 99) && (p
!= 5) && (p
!= 140) && myrpt
->p
.authlevel
&&
7767 (!myrpt
->loginlevel
[0])) return DC_ERROR
;
7768 multimode
= multimode_capable(myrpt
);
7772 case 1: /* retrieve memory */
7773 if(strlen(digitbuf
) < 2) /* needs 2 digits */
7776 for(i
= 0 ; i
< 2 ; i
++){
7777 if((digitbuf
[i
] < '0') || (digitbuf
[i
] > '9'))
7781 r
= retreive_memory(myrpt
, digitbuf
);
7783 rpt_telemetry(myrpt
,MEMNOTFOUND
,NULL
);
7789 if (setrem(myrpt
) == -1) return DC_ERROR
;
7792 case 2: /* set freq and offset */
7795 for(i
= 0, j
= 0, k
= 0, l
= 0 ; digitbuf
[i
] ; i
++){ /* look for M+*K+*O or M+*H+* depending on mode */
7796 if(digitbuf
[i
] == '*'){
7800 if((digitbuf
[i
] < '0') || (digitbuf
[i
] > '9'))
7804 l
++; /* # of digits before first * */
7806 k
++; /* # of digits after first * */
7810 i
= strlen(digitbuf
) - 1;
7812 if((j
> 2) || (l
> 3) || (k
> 6))
7813 goto invalid_freq
; /* &^@#! */
7816 if((j
> 2) || (l
> 4) || (k
> 3))
7817 goto invalid_freq
; /* &^@#! */
7820 /* Wait for M+*K+* */
7823 break; /* Not yet */
7825 /* We have a frequency */
7827 strncpy(tmp
, digitbuf
,sizeof(tmp
) - 1);
7830 s1
= strsep(&s
, "*"); /* Pick off MHz */
7831 s2
= strsep(&s
,"*"); /* Pick off KHz and Hz */
7834 switch(ls2
){ /* Allow partial entry of khz and hz digits for laziness support */
7847 if((s2
[2] != '0')&&(s2
[2] != '5'))
7855 ht
= 10 * (atoi(s2
+(ls2
-1)));
7860 ht
= (atoi(s2
+(ls2
-2)));
7867 /* Check frequency for validity and establish a default mode */
7869 snprintf(freq
, sizeof(freq
), "%s.%03d%02d",s1
, k
, ht
);
7872 printf("New frequency: %s\n", freq
);
7874 split_freq(mhz
, decimals
, freq
);
7878 if(check_freq(myrpt
, m
, d
, &defmode
)) /* Check to see if frequency entered is legit */
7882 if((defmode
== REM_MODE_FM
) && (digitbuf
[i
] == '*')) /* If FM, user must enter and additional offset digit */
7883 break; /* Not yet */
7886 offset
= REM_SIMPLEX
; /* Assume simplex */
7888 if(defmode
== REM_MODE_FM
){
7889 oc
= *s
; /* Pick off offset */
7898 offset
= REM_SIMPLEX
;
7910 offsave
= myrpt
->offset
;
7911 modesave
= myrpt
->remmode
;
7912 strncpy(savestr
, myrpt
->freq
, sizeof(savestr
) - 1);
7913 strncpy(myrpt
->freq
, freq
, sizeof(myrpt
->freq
) - 1);
7914 myrpt
->offset
= offset
;
7915 myrpt
->remmode
= defmode
;
7917 if (setrem(myrpt
) == -1){
7918 myrpt
->offset
= offsave
;
7919 myrpt
->remmode
= modesave
;
7920 strncpy(myrpt
->freq
, savestr
, sizeof(myrpt
->freq
) - 1);
7927 rpt_telemetry(myrpt
,INVFREQ
,NULL
);
7930 case 3: /* set rx PL tone */
7931 for(i
= 0, j
= 0, k
= 0, l
= 0 ; digitbuf
[i
] ; i
++){ /* look for N+*N */
7932 if(digitbuf
[i
] == '*'){
7936 if((digitbuf
[i
] < '0') || (digitbuf
[i
] > '9'))
7945 if((j
> 1) || (k
> 3) || (l
> 1))
7946 return DC_ERROR
; /* &$@^! */
7947 i
= strlen(digitbuf
) - 1;
7948 if((j
!= 1) || (k
< 2)|| (l
!= 1))
7949 break; /* Not yet */
7951 printf("PL digits entered %s\n", digitbuf
);
7953 strncpy(tmp
, digitbuf
, sizeof(tmp
) - 1);
7954 /* see if we have at least 1 */
7955 s
= strchr(tmp
,'*');
7958 strncpy(savestr
, myrpt
->rxpl
, sizeof(savestr
) - 1);
7959 strncpy(myrpt
->rxpl
, tmp
, sizeof(myrpt
->rxpl
) - 1);
7960 if(!strcmp(myrpt
->remote
, remote_rig_rbi
))
7962 strncpy(myrpt
->txpl
, tmp
, sizeof(myrpt
->txpl
) - 1);
7964 if (setrem(myrpt
) == -1){
7965 strncpy(myrpt
->rxpl
, savestr
, sizeof(myrpt
->rxpl
) - 1);
7972 case 4: /* set tx PL tone */
7973 /* cant set tx tone on RBI (rx tone does both) */
7974 if(!strcmp(myrpt
->remote
, remote_rig_rbi
))
7976 if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
7978 for(i
= 0, j
= 0, k
= 0, l
= 0 ; digitbuf
[i
] ; i
++){ /* look for N+*N */
7979 if(digitbuf
[i
] == '*'){
7983 if((digitbuf
[i
] < '0') || (digitbuf
[i
] > '9'))
7992 if((j
> 1) || (k
> 3) || (l
> 1))
7993 return DC_ERROR
; /* &$@^! */
7994 i
= strlen(digitbuf
) - 1;
7995 if((j
!= 1) || (k
< 2)|| (l
!= 1))
7996 break; /* Not yet */
7998 printf("PL digits entered %s\n", digitbuf
);
8000 strncpy(tmp
, digitbuf
, sizeof(tmp
) - 1);
8001 /* see if we have at least 1 */
8002 s
= strchr(tmp
,'*');
8005 strncpy(savestr
, myrpt
->txpl
, sizeof(savestr
) - 1);
8006 strncpy(myrpt
->txpl
, tmp
, sizeof(myrpt
->txpl
) - 1);
8008 if (setrem(myrpt
) == -1){
8009 strncpy(myrpt
->txpl
, savestr
, sizeof(myrpt
->txpl
) - 1);
8017 case 6: /* MODE (FM,USB,LSB,AM) */
8018 if(strlen(digitbuf
) < 1)
8022 return DC_ERROR
; /* Multimode radios only */
8026 split_freq(mhz
, decimals
, myrpt
->freq
);
8028 if(m
< 29) /* No FM allowed below 29MHz! */
8030 myrpt
->remmode
= REM_MODE_FM
;
8032 rpt_telemetry(myrpt
,REMMODE
,NULL
);
8036 myrpt
->remmode
= REM_MODE_USB
;
8037 rpt_telemetry(myrpt
,REMMODE
,NULL
);
8041 myrpt
->remmode
= REM_MODE_LSB
;
8042 rpt_telemetry(myrpt
,REMMODE
,NULL
);
8046 myrpt
->remmode
= REM_MODE_AM
;
8047 rpt_telemetry(myrpt
,REMMODE
,NULL
);
8056 return DC_COMPLETEQUIET
;
8058 /* cant log in when logged in */
8059 if (myrpt
->loginlevel
[0])
8061 *myrpt
->loginuser
= 0;
8062 myrpt
->loginlevel
[0] = 0;
8064 cp1
= strchr(cp
,',');
8065 ast_mutex_lock(&myrpt
->lock
);
8069 cp2
= strchr(cp1
+ 1,',');
8073 strncpy(myrpt
->loginlevel
,cp2
+ 1,
8074 sizeof(myrpt
->loginlevel
) - 1);
8076 strncpy(myrpt
->loginuser
,cp1
+ 1,sizeof(myrpt
->loginuser
));
8077 ast_mutex_unlock(&myrpt
->lock
);
8078 if (myrpt
->p
.archivedir
)
8082 sprintf(str
,"LOGIN,%s,%s",
8083 myrpt
->loginuser
,myrpt
->loginlevel
);
8084 donodelog(myrpt
,str
);
8087 printf("loginuser %s level %s\n",myrpt
->loginuser
,myrpt
->loginlevel
);
8088 rpt_telemetry(myrpt
,REMLOGIN
,NULL
);
8091 return DC_COMPLETEQUIET
;
8092 case 100: /* RX PL Off */
8095 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8096 return DC_COMPLETEQUIET
;
8097 case 101: /* RX PL On */
8100 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8101 return DC_COMPLETEQUIET
;
8102 case 102: /* TX PL Off */
8105 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8106 return DC_COMPLETEQUIET
;
8107 case 103: /* TX PL On */
8110 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8111 return DC_COMPLETEQUIET
;
8112 case 104: /* Low Power */
8113 if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
8115 myrpt
->powerlevel
= REM_LOWPWR
;
8117 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8118 return DC_COMPLETEQUIET
;
8119 case 105: /* Medium Power */
8120 if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
8122 myrpt
->powerlevel
= REM_MEDPWR
;
8124 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8125 return DC_COMPLETEQUIET
;
8126 case 106: /* Hi Power */
8127 if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
8129 myrpt
->powerlevel
= REM_HIPWR
;
8131 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8132 return DC_COMPLETEQUIET
;
8133 case 107: /* Bump down 20Hz */
8134 multimode_bump_freq(myrpt
, -20);
8136 case 108: /* Bump down 100Hz */
8137 multimode_bump_freq(myrpt
, -100);
8139 case 109: /* Bump down 500Hz */
8140 multimode_bump_freq(myrpt
, -500);
8142 case 110: /* Bump up 20Hz */
8143 multimode_bump_freq(myrpt
, 20);
8145 case 111: /* Bump up 100Hz */
8146 multimode_bump_freq(myrpt
, 100);
8148 case 112: /* Bump up 500Hz */
8149 multimode_bump_freq(myrpt
, 500);
8151 case 113: /* Scan down slow */
8152 myrpt
->scantimer
= REM_SCANTIME
;
8153 myrpt
->hfscanmode
= HF_SCAN_DOWN_SLOW
;
8154 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8155 return DC_COMPLETEQUIET
;
8156 case 114: /* Scan down quick */
8157 myrpt
->scantimer
= REM_SCANTIME
;
8158 myrpt
->hfscanmode
= HF_SCAN_DOWN_QUICK
;
8159 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8160 return DC_COMPLETEQUIET
;
8161 case 115: /* Scan down fast */
8162 myrpt
->scantimer
= REM_SCANTIME
;
8163 myrpt
->hfscanmode
= HF_SCAN_DOWN_FAST
;
8164 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8165 return DC_COMPLETEQUIET
;
8166 case 116: /* Scan up slow */
8167 myrpt
->scantimer
= REM_SCANTIME
;
8168 myrpt
->hfscanmode
= HF_SCAN_UP_SLOW
;
8169 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8170 return DC_COMPLETEQUIET
;
8171 case 117: /* Scan up quick */
8172 myrpt
->scantimer
= REM_SCANTIME
;
8173 myrpt
->hfscanmode
= HF_SCAN_UP_QUICK
;
8174 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8175 return DC_COMPLETEQUIET
;
8176 case 118: /* Scan up fast */
8177 myrpt
->scantimer
= REM_SCANTIME
;
8178 myrpt
->hfscanmode
= HF_SCAN_UP_FAST
;
8179 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8180 return DC_COMPLETEQUIET
;
8181 case 119: /* Tune Request */
8182 /* if not currently going, and valid to do */
8183 if((!myrpt
->tunerequest
) &&
8184 ((!strcmp(myrpt
->remote
, remote_rig_ft897
) ||
8185 !strcmp(myrpt
->remote
, remote_rig_ic706
)) )) {
8186 myrpt
->remotetx
= 0;
8187 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_UNKEY
);
8188 myrpt
->tunerequest
= 1;
8189 rpt_telemetry(myrpt
,TUNE
,NULL
);
8190 return DC_COMPLETEQUIET
;
8193 case 5: /* Long Status */
8194 rpt_telemetry(myrpt
,REMLONGSTATUS
,NULL
);
8195 return DC_COMPLETEQUIET
;
8196 case 140: /* Short Status */
8197 rpt_telemetry(myrpt
,REMSHORTSTATUS
,NULL
);
8198 return DC_COMPLETEQUIET
;
8215 do_dtmf_local(myrpt
,remdtmfstr
[p
- 200]);
8216 return DC_COMPLETEQUIET
;
8220 return DC_INDETERMINATE
;
8224 static int handle_remote_dtmf_digit(struct rpt
*myrpt
,char c
, char *keyed
, int phonemode
)
8227 int ret
,res
= 0,src
;
8229 time(&myrpt
->last_activity_time
);
8230 /* Stop scan mode if in scan mode */
8231 if(myrpt
->hfscanmode
){
8238 if ((myrpt
->dtmf_time_rem
+ DTMF_TIMEOUT
) < now
)
8240 myrpt
->dtmfidx
= -1;
8241 myrpt
->dtmfbuf
[0] = 0;
8242 myrpt
->dtmf_time_rem
= 0;
8244 /* if decode not active */
8245 if (myrpt
->dtmfidx
== -1)
8247 /* if not lead-in digit, dont worry */
8248 if (c
!= myrpt
->p
.funcchar
)
8250 if (!myrpt
->p
.propagate_dtmf
)
8252 rpt_mutex_lock(&myrpt
->lock
);
8253 do_dtmf_local(myrpt
,c
);
8254 rpt_mutex_unlock(&myrpt
->lock
);
8259 myrpt
->dtmfbuf
[0] = 0;
8260 myrpt
->dtmf_time_rem
= now
;
8263 /* if too many in buffer, start over */
8264 if (myrpt
->dtmfidx
>= MAXDTMF
)
8267 myrpt
->dtmfbuf
[0] = 0;
8268 myrpt
->dtmf_time_rem
= now
;
8270 if (c
== myrpt
->p
.funcchar
)
8272 /* if star at beginning, or 2 together, erase buffer */
8273 if ((myrpt
->dtmfidx
< 1) ||
8274 (myrpt
->dtmfbuf
[myrpt
->dtmfidx
- 1] == myrpt
->p
.funcchar
))
8277 myrpt
->dtmfbuf
[0] = 0;
8278 myrpt
->dtmf_time_rem
= now
;
8282 myrpt
->dtmfbuf
[myrpt
->dtmfidx
++] = c
;
8283 myrpt
->dtmfbuf
[myrpt
->dtmfidx
] = 0;
8284 myrpt
->dtmf_time_rem
= now
;
8288 if (phonemode
> 1) src
= SOURCE_DPHONE
;
8289 else if (phonemode
) src
= SOURCE_PHONE
;
8290 ret
= collect_function_digits(myrpt
, myrpt
->dtmfbuf
, src
, NULL
);
8294 case DC_INDETERMINATE
:
8299 if (keyed
) *keyed
= 1;
8305 myrpt
->dtmfbuf
[0] = 0;
8312 case DC_COMPLETEQUIET
:
8313 myrpt
->totalexecdcommands
++;
8314 myrpt
->dailyexecdcommands
++;
8315 strncpy(myrpt
->lastdtmfcommand
, myrpt
->dtmfbuf
, MAXDTMF
-1);
8316 myrpt
->lastdtmfcommand
[MAXDTMF
-1] = '\0';
8317 myrpt
->dtmfbuf
[0] = 0;
8318 myrpt
->dtmfidx
= -1;
8319 myrpt
->dtmf_time_rem
= 0;
8324 myrpt
->dtmfbuf
[0] = 0;
8325 myrpt
->dtmfidx
= -1;
8326 myrpt
->dtmf_time_rem
= 0;
8334 static int handle_remote_data(struct rpt
*myrpt
, char *str
)
8336 char tmp
[300],cmd
[300],dest
[300],src
[300],c
;
8339 /* put string in our buffer */
8340 strncpy(tmp
,str
,sizeof(tmp
) - 1);
8341 if (!strcmp(tmp
,discstr
)) return 0;
8343 #ifndef DO_NOT_NOTIFY_MDC1200_ON_REMOTE_BASES
8346 if (sscanf(tmp
,"%s %s %x",cmd
,src
,&seq
) != 3)
8348 ast_log(LOG_WARNING
, "Unable to parse ident string %s\n",str
);
8351 mdc1200_notify(myrpt
,src
,seq
);
8355 if (sscanf(tmp
,"%s %s %s %d %c",cmd
,dest
,src
,&seq
,&c
) != 5)
8357 ast_log(LOG_WARNING
, "Unable to parse link string %s\n",str
);
8360 if (strcmp(cmd
,"D"))
8362 ast_log(LOG_WARNING
, "Unable to parse link string %s\n",str
);
8365 /* if not for me, ignore */
8366 if (strcmp(dest
,myrpt
->name
)) return 0;
8367 if (myrpt
->p
.archivedir
)
8371 sprintf(str
,"DTMF,%c",c
);
8372 donodelog(myrpt
,str
);
8374 c
= func_xlat(myrpt
,c
,&myrpt
->p
.outxlat
);
8376 res
= handle_remote_dtmf_digit(myrpt
,c
, NULL
, 0);
8379 rpt_telemetry(myrpt
,COMPLETE
,NULL
);
8383 static int handle_remote_phone_dtmf(struct rpt
*myrpt
, char c
, char *keyed
, int phonemode
)
8388 if (keyed
&& *keyed
&& (c
== myrpt
->p
.endchar
))
8391 return DC_INDETERMINATE
;
8394 if (myrpt
->p
.archivedir
)
8398 sprintf(str
,"DTMF(P),%c",c
);
8399 donodelog(myrpt
,str
);
8401 res
= handle_remote_dtmf_digit(myrpt
,c
,keyed
, phonemode
);
8404 rpt_telemetry(myrpt
,COMPLETE
,NULL
);
8408 static int attempt_reconnect(struct rpt
*myrpt
, struct rpt_link
*l
)
8410 char *val
, *s
, *s1
, *s2
, *tele
;
8411 char tmp
[300], deststr
[300] = "";
8413 val
= node_lookup(myrpt
,l
->name
);
8416 fprintf(stderr
,"attempt_reconnect: cannot find node %s\n",l
->name
);
8420 rpt_mutex_lock(&myrpt
->lock
);
8421 /* remove from queue */
8422 remque((struct qelem
*) l
);
8423 rpt_mutex_unlock(&myrpt
->lock
);
8424 strncpy(tmp
,val
,sizeof(tmp
) - 1);
8426 s1
= strsep(&s
,",");
8427 s2
= strsep(&s
,",");
8428 snprintf(deststr
, sizeof(deststr
), "IAX2/%s", s1
);
8429 tele
= strchr(deststr
, '/');
8431 fprintf(stderr
,"attempt_reconnect:Dial number (%s) must be in format tech/number\n",deststr
);
8437 l
->thisconnected
= 0;
8438 l
->chan
= ast_request(deststr
, AST_FORMAT_SLINEAR
, tele
,NULL
);
8440 ast_set_read_format(l
->chan
, AST_FORMAT_SLINEAR
);
8441 ast_set_write_format(l
->chan
, AST_FORMAT_SLINEAR
);
8442 l
->chan
->whentohangup
= 0;
8443 l
->chan
->appl
= "Apprpt";
8444 l
->chan
->data
= "(Remote Rx)";
8445 if (option_verbose
> 2)
8446 ast_verbose(VERBOSE_PREFIX_3
"rpt (attempt_reconnect) initiating call to %s/%s on %s\n",
8447 deststr
, tele
, l
->chan
->name
);
8448 if(l
->chan
->cid
.cid_num
)
8449 free(l
->chan
->cid
.cid_num
);
8450 l
->chan
->cid
.cid_num
= strdup(myrpt
->name
);
8451 ast_call(l
->chan
,tele
,999);
8456 if (option_verbose
> 2)
8457 ast_verbose(VERBOSE_PREFIX_3
"Unable to place call to %s/%s on %s\n",
8458 deststr
,tele
,l
->chan
->name
);
8461 rpt_mutex_lock(&myrpt
->lock
);
8462 /* put back in queue */
8463 insque((struct qelem
*)l
,(struct qelem
*)myrpt
->links
.next
);
8464 rpt_mutex_unlock(&myrpt
->lock
);
8465 ast_log(LOG_NOTICE
,"Reconnect Attempt to %s in process\n",l
->name
);
8469 /* 0 return=continue, 1 return = break, -1 return = error */
8470 static void local_dtmf_helper(struct rpt
*myrpt
,char c
)
8473 pthread_attr_t attr
;
8474 char cmd
[MAXDTMF
+1] = "";
8476 if (myrpt
->p
.archivedir
)
8480 sprintf(str
,"DTMF,MAIN,%c",c
);
8481 donodelog(myrpt
,str
);
8483 if (c
== myrpt
->p
.endchar
)
8485 /* if in simple mode, kill autopatch */
8486 if (myrpt
->p
.simple
&& myrpt
->callmode
)
8488 rpt_mutex_lock(&myrpt
->lock
);
8489 myrpt
->callmode
= 0;
8490 rpt_mutex_unlock(&myrpt
->lock
);
8491 rpt_telemetry(myrpt
,TERM
,NULL
);
8494 rpt_mutex_lock(&myrpt
->lock
);
8496 if (myrpt
->cmdnode
[0])
8498 myrpt
->cmdnode
[0] = 0;
8499 myrpt
->dtmfidx
= -1;
8500 myrpt
->dtmfbuf
[0] = 0;
8501 rpt_mutex_unlock(&myrpt
->lock
);
8502 rpt_telemetry(myrpt
,COMPLETE
,NULL
);
8506 rpt_mutex_unlock(&myrpt
->lock
);
8507 if (myrpt
->p
.propagate_phonedtmf
)
8508 do_dtmf_phone(myrpt
,NULL
,c
);
8512 rpt_mutex_lock(&myrpt
->lock
);
8513 if (myrpt
->cmdnode
[0])
8515 rpt_mutex_unlock(&myrpt
->lock
);
8516 send_link_dtmf(myrpt
,c
);
8519 if (!myrpt
->p
.simple
)
8521 if (c
== myrpt
->p
.funcchar
)
8524 myrpt
->dtmfbuf
[myrpt
->dtmfidx
] = 0;
8525 rpt_mutex_unlock(&myrpt
->lock
);
8526 time(&myrpt
->dtmf_time
);
8529 else if ((c
!= myrpt
->p
.endchar
) && (myrpt
->dtmfidx
>= 0))
8531 time(&myrpt
->dtmf_time
);
8533 if (myrpt
->dtmfidx
< MAXDTMF
)
8535 myrpt
->dtmfbuf
[myrpt
->dtmfidx
++] = c
;
8536 myrpt
->dtmfbuf
[myrpt
->dtmfidx
] = 0;
8538 strncpy(cmd
, myrpt
->dtmfbuf
, sizeof(cmd
) - 1);
8540 rpt_mutex_unlock(&myrpt
->lock
);
8541 res
= collect_function_digits(myrpt
, cmd
, SOURCE_RPT
, NULL
);
8542 rpt_mutex_lock(&myrpt
->lock
);
8544 case DC_INDETERMINATE
:
8548 myrpt
->dtmfbuf
[0] = 0;
8551 case DC_COMPLETEQUIET
:
8552 myrpt
->totalexecdcommands
++;
8553 myrpt
->dailyexecdcommands
++;
8554 strncpy(myrpt
->lastdtmfcommand
, cmd
, MAXDTMF
-1);
8555 myrpt
->lastdtmfcommand
[MAXDTMF
-1] = '\0';
8556 myrpt
->dtmfbuf
[0] = 0;
8557 myrpt
->dtmfidx
= -1;
8558 myrpt
->dtmf_time
= 0;
8563 myrpt
->dtmfbuf
[0] = 0;
8564 myrpt
->dtmfidx
= -1;
8565 myrpt
->dtmf_time
= 0;
8568 if(res
!= DC_INDETERMINATE
) {
8569 rpt_mutex_unlock(&myrpt
->lock
);
8575 else /* if simple */
8577 if ((!myrpt
->callmode
) && (c
== myrpt
->p
.funcchar
))
8579 myrpt
->callmode
= 1;
8580 myrpt
->patchnoct
= 0;
8581 myrpt
->patchquiet
= 0;
8582 myrpt
->patchfarenddisconnect
= 0;
8583 myrpt
->patchdialtime
= 0;
8584 strncpy(myrpt
->patchcontext
, myrpt
->p
.ourcontext
, MAXPATCHCONTEXT
);
8586 myrpt
->exten
[myrpt
->cidx
] = 0;
8587 rpt_mutex_unlock(&myrpt
->lock
);
8588 pthread_attr_init(&attr
);
8589 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
8590 ast_pthread_create(&myrpt
->rpt_call_thread
,&attr
,rpt_call
,(void *)myrpt
);
8594 if (myrpt
->callmode
== 1)
8596 myrpt
->exten
[myrpt
->cidx
++] = c
;
8597 myrpt
->exten
[myrpt
->cidx
] = 0;
8598 /* if this exists */
8599 if (ast_exists_extension(myrpt
->pchannel
,myrpt
->patchcontext
,myrpt
->exten
,1,NULL
))
8601 myrpt
->callmode
= 2;
8602 rpt_mutex_unlock(&myrpt
->lock
);
8603 if(!myrpt
->patchquiet
)
8604 rpt_telemetry(myrpt
,PROC
,NULL
);
8607 /* if can continue, do so */
8608 if (!ast_canmatch_extension(myrpt
->pchannel
,myrpt
->patchcontext
,myrpt
->exten
,1,NULL
))
8610 /* call has failed, inform user */
8611 myrpt
->callmode
= 4;
8613 rpt_mutex_unlock(&myrpt
->lock
);
8616 if ((myrpt
->callmode
== 2) || (myrpt
->callmode
== 3))
8620 rpt_mutex_unlock(&myrpt
->lock
);
8621 if ((myrpt
->dtmfidx
< 0) && myrpt
->p
.propagate_phonedtmf
)
8622 do_dtmf_phone(myrpt
,NULL
,c
);
8627 /* place an ID event in the telemetry queue */
8629 static void queue_id(struct rpt
*myrpt
)
8631 if(myrpt
->p
.idtime
){ /* ID time must be non-zero */
8632 myrpt
->mustid
= myrpt
->tailid
= 0;
8633 myrpt
->idtimer
= myrpt
->p
.idtime
; /* Reset our ID timer */
8634 rpt_mutex_unlock(&myrpt
->lock
);
8635 rpt_telemetry(myrpt
,ID
,NULL
);
8636 rpt_mutex_lock(&myrpt
->lock
);
8641 /* must be called locked */
8643 static void do_scheduler(struct rpt
*myrpt
)
8647 struct ast_variable
*skedlist
;
8648 char *strs
[5],*vp
,*val
,value
[100];
8650 memcpy(&myrpt
->lasttv
, &myrpt
->curtv
, sizeof(struct timeval
));
8652 if( (res
= gettimeofday(&myrpt
->curtv
, NULL
)) < 0)
8653 ast_log(LOG_NOTICE
, "Scheduler gettime of day returned: %s\n", strerror(res
));
8655 /* Try to get close to a 1 second resolution */
8657 if(myrpt
->lasttv
.tv_sec
== myrpt
->curtv
.tv_sec
)
8660 rpt_localtime(&myrpt
->curtv
.tv_sec
, &tmnow
);
8662 /* If midnight, then reset all daily statistics */
8664 if((tmnow
.tm_hour
== 0)&&(tmnow
.tm_min
== 0)&&(tmnow
.tm_sec
== 0)){
8665 myrpt
->dailykeyups
= 0;
8666 myrpt
->dailytxtime
= 0;
8667 myrpt
->dailykerchunks
= 0;
8668 myrpt
->dailyexecdcommands
= 0;
8671 if(tmnow
.tm_sec
!= 0)
8674 /* Code below only executes once per minute */
8677 /* Don't schedule if remote */
8682 /* Don't schedule if disabled */
8684 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].schedulerdisable
){
8686 ast_log(LOG_NOTICE
, "Scheduler disabled\n");
8690 if(!myrpt
->p
.skedstanzaname
){ /* No stanza means we do nothing */
8692 ast_log(LOG_NOTICE
,"No stanza for scheduler in rpt.conf\n");
8696 /* get pointer to linked list of scheduler entries */
8697 skedlist
= ast_variable_browse(myrpt
->cfg
, myrpt
->p
.skedstanzaname
);
8700 ast_log(LOG_NOTICE
, "Time now: %02d:%02d %02d %02d %02d\n",
8701 tmnow
.tm_hour
,tmnow
.tm_min
,tmnow
.tm_mday
,tmnow
.tm_mon
+ 1, tmnow
.tm_wday
);
8704 for(; skedlist
; skedlist
= skedlist
->next
){
8706 ast_log(LOG_NOTICE
, "Scheduler entry %s = %s being considered\n",skedlist
->name
, skedlist
->value
);
8707 strncpy(value
,skedlist
->value
,99);
8709 /* point to the substrings for minute, hour, dom, month, and dow */
8710 for( i
= 0, vp
= value
; i
< 5; i
++){
8713 while((*vp
== ' ') || (*vp
== 0x09)) /* get rid of any leading white space */
8715 strs
[i
] = vp
; /* save pointer to beginning of substring */
8716 while((*vp
!= ' ') && (*vp
!= 0x09) && (*vp
!= 0)) /* skip over substring */
8719 *vp
++ = 0; /* mark end of substring */
8722 ast_log(LOG_NOTICE
, "i = %d, min = %s, hour = %s, mday=%s, mon=%s, wday=%s\n",i
,
8723 strs
[0], strs
[1], strs
[2], strs
[3], strs
[4]);
8725 if((*strs
[0] != '*')&&(atoi(strs
[0]) != tmnow
.tm_min
))
8727 if((*strs
[1] != '*')&&(atoi(strs
[1]) != tmnow
.tm_hour
))
8729 if((*strs
[2] != '*')&&(atoi(strs
[2]) != tmnow
.tm_mday
))
8731 if((*strs
[3] != '*')&&(atoi(strs
[3]) != tmnow
.tm_mon
+ 1))
8733 if(atoi(strs
[4]) == 7)
8735 if((*strs
[4] != '*')&&(atoi(strs
[4]) != tmnow
.tm_wday
))
8738 ast_log(LOG_NOTICE
, "Executing scheduler entry %s = %s\n", skedlist
->name
, skedlist
->value
);
8739 if(atoi(skedlist
->name
) == 0)
8740 return; /* Zero is reserved for the startup macro */
8741 val
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->p
.macro
, skedlist
->name
);
8743 ast_log(LOG_WARNING
,"Scheduler could not find macro %s\n",skedlist
->name
);
8744 return; /* Macro not found */
8746 if ((MAXMACRO
- strlen(myrpt
->macrobuf
)) < strlen(val
)){
8747 ast_log(LOG_WARNING
, "Scheduler could not execute macro %s: Macro buffer full\n",
8749 return; /* Macro buffer full */
8751 myrpt
->macrotimer
= MACROTIME
;
8752 strncat(myrpt
->macrobuf
,val
,MAXMACRO
- 1);
8755 ast_log(LOG_WARNING
,"Malformed scheduler entry in rpt.conf: %s = %s\n",
8756 skedlist
->name
, skedlist
->value
);
8762 /* single thread with one file (request) to dial */
8763 static void *rpt(void *this)
8765 struct rpt
*myrpt
= (struct rpt
*)this;
8766 char *tele
,*idtalkover
,c
;
8767 int ms
= MSWAIT
,i
,lasttx
=0,val
,remrx
=0,identqueued
,othertelemqueued
;
8768 int tailmessagequeued
,ctqueued
,dtmfed
;
8769 struct ast_channel
*who
;
8770 ZT_CONFINFO ci
; /* conference info */
8772 struct rpt_link
*l
,*m
;
8773 struct rpt_tele
*telem
;
8774 char tmpstr
[300],lstr
[MAXLINKLIST
];
8777 if (myrpt
->p
.archivedir
) mkdir(myrpt
->p
.archivedir
,0600);
8778 sprintf(tmpstr
,"%s/%s",myrpt
->p
.archivedir
,myrpt
->name
);
8780 rpt_mutex_lock(&myrpt
->lock
);
8782 telem
= myrpt
->tele
.next
;
8783 while(telem
!= &myrpt
->tele
)
8785 ast_softhangup(telem
->chan
,AST_SOFTHANGUP_DEV
);
8786 telem
= telem
->next
;
8788 rpt_mutex_unlock(&myrpt
->lock
);
8789 /* find our index, and load the vars initially */
8790 for(i
= 0; i
< nrpts
; i
++)
8792 if (&rpt_vars
[i
] == myrpt
)
8798 rpt_mutex_lock(&myrpt
->lock
);
8799 strncpy(tmpstr
,myrpt
->rxchanname
,sizeof(tmpstr
) - 1);
8800 tele
= strchr(tmpstr
,'/');
8803 fprintf(stderr
,"rpt:Rxchannel Dial number (%s) must be in format tech/number\n",myrpt
->rxchanname
);
8804 rpt_mutex_unlock(&myrpt
->lock
);
8805 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8809 myrpt
->rxchannel
= ast_request(tmpstr
,AST_FORMAT_SLINEAR
,tele
,NULL
);
8810 myrpt
->zaprxchannel
= NULL
;
8811 if (!strcasecmp(tmpstr
,"Zap"))
8812 myrpt
->zaprxchannel
= myrpt
->rxchannel
;
8813 if (myrpt
->rxchannel
)
8815 if (myrpt
->rxchannel
->_state
== AST_STATE_BUSY
)
8817 fprintf(stderr
,"rpt:Sorry unable to obtain Rx channel\n");
8818 rpt_mutex_unlock(&myrpt
->lock
);
8819 ast_hangup(myrpt
->rxchannel
);
8820 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8823 ast_set_read_format(myrpt
->rxchannel
,AST_FORMAT_SLINEAR
);
8824 ast_set_write_format(myrpt
->rxchannel
,AST_FORMAT_SLINEAR
);
8825 #ifdef AST_CDR_FLAG_POST_DISABLED
8826 ast_set_flag(myrpt
->rxchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
8828 myrpt
->rxchannel
->whentohangup
= 0;
8829 myrpt
->rxchannel
->appl
= "Apprpt";
8830 myrpt
->rxchannel
->data
= "(Repeater Rx)";
8831 if (option_verbose
> 2)
8832 ast_verbose(VERBOSE_PREFIX_3
"rpt (Rx) initiating call to %s/%s on %s\n",
8833 tmpstr
,tele
,myrpt
->rxchannel
->name
);
8834 ast_call(myrpt
->rxchannel
,tele
,999);
8835 if (myrpt
->rxchannel
->_state
!= AST_STATE_UP
)
8837 rpt_mutex_unlock(&myrpt
->lock
);
8838 ast_hangup(myrpt
->rxchannel
);
8839 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8845 fprintf(stderr
,"rpt:Sorry unable to obtain Rx channel\n");
8846 rpt_mutex_unlock(&myrpt
->lock
);
8847 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8850 myrpt
->zaptxchannel
= NULL
;
8851 if (myrpt
->txchanname
)
8853 strncpy(tmpstr
,myrpt
->txchanname
,sizeof(tmpstr
) - 1);
8854 tele
= strchr(tmpstr
,'/');
8857 fprintf(stderr
,"rpt:Txchannel Dial number (%s) must be in format tech/number\n",myrpt
->txchanname
);
8858 rpt_mutex_unlock(&myrpt
->lock
);
8859 ast_hangup(myrpt
->rxchannel
);
8860 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8864 myrpt
->txchannel
= ast_request(tmpstr
,AST_FORMAT_SLINEAR
,tele
,NULL
);
8865 if (!strcasecmp(tmpstr
,"Zap"))
8866 myrpt
->zaptxchannel
= myrpt
->txchannel
;
8867 if (myrpt
->txchannel
)
8869 if (myrpt
->txchannel
->_state
== AST_STATE_BUSY
)
8871 fprintf(stderr
,"rpt:Sorry unable to obtain Tx channel\n");
8872 rpt_mutex_unlock(&myrpt
->lock
);
8873 ast_hangup(myrpt
->txchannel
);
8874 ast_hangup(myrpt
->rxchannel
);
8875 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8878 ast_set_read_format(myrpt
->txchannel
,AST_FORMAT_SLINEAR
);
8879 ast_set_write_format(myrpt
->txchannel
,AST_FORMAT_SLINEAR
);
8880 #ifdef AST_CDR_FLAG_POST_DISABLED
8881 ast_set_flag(myrpt
->txchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
8883 myrpt
->txchannel
->whentohangup
= 0;
8884 myrpt
->txchannel
->appl
= "Apprpt";
8885 myrpt
->txchannel
->data
= "(Repeater Tx)";
8886 if (option_verbose
> 2)
8887 ast_verbose(VERBOSE_PREFIX_3
"rpt (Tx) initiating call to %s/%s on %s\n",
8888 tmpstr
,tele
,myrpt
->txchannel
->name
);
8889 ast_call(myrpt
->txchannel
,tele
,999);
8890 if (myrpt
->rxchannel
->_state
!= AST_STATE_UP
)
8892 rpt_mutex_unlock(&myrpt
->lock
);
8893 ast_hangup(myrpt
->rxchannel
);
8894 ast_hangup(myrpt
->txchannel
);
8895 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8901 fprintf(stderr
,"rpt:Sorry unable to obtain Tx channel\n");
8902 rpt_mutex_unlock(&myrpt
->lock
);
8903 ast_hangup(myrpt
->rxchannel
);
8904 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8910 myrpt
->txchannel
= myrpt
->rxchannel
;
8912 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_KEY
);
8913 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_UNKEY
);
8914 /* allocate a pseudo-channel thru asterisk */
8915 myrpt
->pchannel
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
8916 if (!myrpt
->pchannel
)
8918 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
8919 rpt_mutex_unlock(&myrpt
->lock
);
8920 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
8921 ast_hangup(myrpt
->txchannel
);
8922 ast_hangup(myrpt
->rxchannel
);
8923 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8926 #ifdef AST_CDR_FLAG_POST_DISABLED
8927 ast_set_flag(myrpt
->pchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
8929 if (!myrpt
->zaprxchannel
) myrpt
->zaprxchannel
= myrpt
->pchannel
;
8930 if (!myrpt
->zaptxchannel
)
8932 /* allocate a pseudo-channel thru asterisk */
8933 myrpt
->zaptxchannel
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
8934 if (!myrpt
->zaptxchannel
)
8936 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
8937 rpt_mutex_unlock(&myrpt
->lock
);
8938 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
8939 ast_hangup(myrpt
->txchannel
);
8940 ast_hangup(myrpt
->rxchannel
);
8941 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8944 ast_set_read_format(myrpt
->zaptxchannel
,AST_FORMAT_SLINEAR
);
8945 ast_set_write_format(myrpt
->zaptxchannel
,AST_FORMAT_SLINEAR
);
8946 #ifdef AST_CDR_FLAG_POST_DISABLED
8947 ast_set_flag(myrpt
->zaptxchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
8950 /* allocate a pseudo-channel thru asterisk */
8951 myrpt
->monchannel
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
8952 if (!myrpt
->monchannel
)
8954 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
8955 rpt_mutex_unlock(&myrpt
->lock
);
8956 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
8957 ast_hangup(myrpt
->txchannel
);
8958 ast_hangup(myrpt
->rxchannel
);
8959 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8962 ast_set_read_format(myrpt
->monchannel
,AST_FORMAT_SLINEAR
);
8963 ast_set_write_format(myrpt
->monchannel
,AST_FORMAT_SLINEAR
);
8964 #ifdef AST_CDR_FLAG_POST_DISABLED
8965 ast_set_flag(myrpt
->monchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
8967 /* make a conference for the tx */
8969 ci
.confno
= -1; /* make a new conf */
8970 ci
.confmode
= ZT_CONF_CONF
| ZT_CONF_LISTENER
;
8971 /* first put the channel on the conference in proper mode */
8972 if (ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_SETCONF
,&ci
) == -1)
8974 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
8975 rpt_mutex_unlock(&myrpt
->lock
);
8976 ast_hangup(myrpt
->pchannel
);
8977 ast_hangup(myrpt
->monchannel
);
8978 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
8979 ast_hangup(myrpt
->txchannel
);
8980 ast_hangup(myrpt
->rxchannel
);
8981 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8984 /* save tx conference number */
8985 myrpt
->txconf
= ci
.confno
;
8986 /* make a conference for the pseudo */
8988 ci
.confno
= -1; /* make a new conf */
8989 ci
.confmode
= ((myrpt
->p
.duplex
== 2) || (myrpt
->p
.duplex
== 4)) ? ZT_CONF_CONFANNMON
:
8990 (ZT_CONF_CONF
| ZT_CONF_LISTENER
| ZT_CONF_TALKER
);
8991 /* first put the channel on the conference in announce mode */
8992 if (ioctl(myrpt
->pchannel
->fds
[0],ZT_SETCONF
,&ci
) == -1)
8994 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
8995 rpt_mutex_unlock(&myrpt
->lock
);
8996 ast_hangup(myrpt
->pchannel
);
8997 ast_hangup(myrpt
->monchannel
);
8998 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
8999 ast_hangup(myrpt
->txchannel
);
9000 ast_hangup(myrpt
->rxchannel
);
9001 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
9004 /* save pseudo channel conference number */
9005 myrpt
->conf
= ci
.confno
;
9006 /* make a conference for the pseudo */
9008 if ((strstr(myrpt
->txchannel
->name
,"pseudo") == NULL
) &&
9009 (myrpt
->zaptxchannel
== myrpt
->txchannel
))
9011 /* get tx channel's port number */
9012 if (ioctl(myrpt
->txchannel
->fds
[0],ZT_CHANNO
,&ci
.confno
) == -1)
9014 ast_log(LOG_WARNING
, "Unable to set tx channel's chan number\n");
9015 rpt_mutex_unlock(&myrpt
->lock
);
9016 ast_hangup(myrpt
->pchannel
);
9017 ast_hangup(myrpt
->monchannel
);
9018 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
9019 ast_hangup(myrpt
->txchannel
);
9020 ast_hangup(myrpt
->rxchannel
);
9021 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
9024 ci
.confmode
= ZT_CONF_MONITORTX
;
9028 ci
.confno
= myrpt
->txconf
;
9029 ci
.confmode
= ZT_CONF_CONFANNMON
;
9031 /* first put the channel on the conference in announce mode */
9032 if (ioctl(myrpt
->monchannel
->fds
[0],ZT_SETCONF
,&ci
) == -1)
9034 ast_log(LOG_WARNING
, "Unable to set conference mode for monitor\n");
9035 rpt_mutex_unlock(&myrpt
->lock
);
9036 ast_hangup(myrpt
->pchannel
);
9037 ast_hangup(myrpt
->monchannel
);
9038 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
9039 ast_hangup(myrpt
->txchannel
);
9040 ast_hangup(myrpt
->rxchannel
);
9041 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
9044 /* allocate a pseudo-channel thru asterisk */
9045 myrpt
->txpchannel
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
9046 if (!myrpt
->txpchannel
)
9048 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
9049 rpt_mutex_unlock(&myrpt
->lock
);
9050 ast_hangup(myrpt
->pchannel
);
9051 ast_hangup(myrpt
->monchannel
);
9052 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
9053 ast_hangup(myrpt
->txchannel
);
9054 ast_hangup(myrpt
->rxchannel
);
9055 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
9058 #ifdef AST_CDR_FLAG_POST_DISABLED
9059 ast_set_flag(myrpt
->txpchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
9061 /* make a conference for the tx */
9063 ci
.confno
= myrpt
->txconf
;
9064 ci
.confmode
= ZT_CONF_CONF
| ZT_CONF_TALKER
;
9065 /* first put the channel on the conference in proper mode */
9066 if (ioctl(myrpt
->txpchannel
->fds
[0],ZT_SETCONF
,&ci
) == -1)
9068 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
9069 rpt_mutex_unlock(&myrpt
->lock
);
9070 ast_hangup(myrpt
->txpchannel
);
9071 ast_hangup(myrpt
->monchannel
);
9072 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
9073 ast_hangup(myrpt
->txchannel
);
9074 ast_hangup(myrpt
->rxchannel
);
9075 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
9078 /* Now, the idea here is to copy from the physical rx channel buffer
9079 into the pseudo tx buffer, and from the pseudo rx buffer into the
9080 tx channel buffer */
9081 myrpt
->links
.next
= &myrpt
->links
;
9082 myrpt
->links
.prev
= &myrpt
->links
;
9083 myrpt
->tailtimer
= 0;
9085 myrpt
->tmsgtimer
= myrpt
->p
.tailmessagetime
;
9086 myrpt
->idtimer
= myrpt
->p
.politeid
;
9087 myrpt
->mustid
= myrpt
->tailid
= 0;
9088 myrpt
->callmode
= 0;
9089 myrpt
->tounkeyed
= 0;
9090 myrpt
->tonotify
= 0;
9091 myrpt
->retxtimer
= 0;
9092 myrpt
->rerxtimer
= 0;
9093 myrpt
->skedtimer
= 0;
9094 myrpt
->tailevent
= 0;
9097 idtalkover
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->name
, "idtalkover");
9098 myrpt
->dtmfidx
= -1;
9099 myrpt
->dtmfbuf
[0] = 0;
9100 myrpt
->rem_dtmfidx
= -1;
9101 myrpt
->rem_dtmfbuf
[0] = 0;
9102 myrpt
->dtmf_time
= 0;
9103 myrpt
->rem_dtmf_time
= 0;
9104 myrpt
->disgorgetime
= 0;
9105 myrpt
->lastnodewhichkeyedusup
[0] = '\0';
9106 myrpt
->dailytxtime
= 0;
9107 myrpt
->totaltxtime
= 0;
9108 myrpt
->dailykeyups
= 0;
9109 myrpt
->totalkeyups
= 0;
9110 myrpt
->dailykerchunks
= 0;
9111 myrpt
->totalkerchunks
= 0;
9112 myrpt
->dailyexecdcommands
= 0;
9113 myrpt
->totalexecdcommands
= 0;
9114 myrpt
->timeouts
= 0;
9115 myrpt
->exten
[0] = '\0';
9116 myrpt
->lastdtmfcommand
[0] = '\0';
9117 if (myrpt
->p
.startupmacro
)
9119 snprintf(myrpt
->macrobuf
,MAXMACRO
- 1,"PPPP%s",myrpt
->p
.startupmacro
);
9121 rpt_mutex_unlock(&myrpt
->lock
);
9123 ast_channel_setoption(myrpt
->rxchannel
,AST_OPTION_RELAXDTMF
,&val
,sizeof(char),0);
9125 ast_channel_setoption(myrpt
->rxchannel
,AST_OPTION_TONE_VERIFY
,&val
,sizeof(char),0);
9126 if (myrpt
->p
.archivedir
) donodelog(myrpt
,"STARTUP");
9130 struct ast_frame
*f
,*f1
,*f2
;
9131 struct ast_channel
*cs
[300],*cs1
[300];
9132 int totx
=0,elap
=0,n
,x
,toexit
=0;
9135 if((myrpt
->disgorgetime
) && (time(NULL
) >= myrpt
->disgorgetime
)){
9136 struct rpt_link
*zl
;
9137 struct rpt_tele
*zt
;
9139 myrpt
->disgorgetime
= 0;
9140 ast_log(LOG_NOTICE
,"********** Variable Dump Start (app_rpt) **********\n");
9141 ast_log(LOG_NOTICE
,"totx = %d\n",totx
);
9142 ast_log(LOG_NOTICE
,"remrx = %d\n",remrx
);
9143 ast_log(LOG_NOTICE
,"lasttx = %d\n",lasttx
);
9144 ast_log(LOG_NOTICE
,"elap = %d\n",elap
);
9145 ast_log(LOG_NOTICE
,"toexit = %d\n",toexit
);
9147 ast_log(LOG_NOTICE
,"myrpt->keyed = %d\n",myrpt
->keyed
);
9148 ast_log(LOG_NOTICE
,"myrpt->localtx = %d\n",myrpt
->localtx
);
9149 ast_log(LOG_NOTICE
,"myrpt->callmode = %d\n",myrpt
->callmode
);
9150 ast_log(LOG_NOTICE
,"myrpt->mustid = %d\n",myrpt
->mustid
);
9151 ast_log(LOG_NOTICE
,"myrpt->tounkeyed = %d\n",myrpt
->tounkeyed
);
9152 ast_log(LOG_NOTICE
,"myrpt->tonotify = %d\n",myrpt
->tonotify
);
9153 ast_log(LOG_NOTICE
,"myrpt->retxtimer = %ld\n",myrpt
->retxtimer
);
9154 ast_log(LOG_NOTICE
,"myrpt->totimer = %d\n",myrpt
->totimer
);
9155 ast_log(LOG_NOTICE
,"myrpt->tailtimer = %d\n",myrpt
->tailtimer
);
9156 ast_log(LOG_NOTICE
,"myrpt->tailevent = %d\n",myrpt
->tailevent
);
9158 zl
= myrpt
->links
.next
;
9159 while(zl
!= &myrpt
->links
){
9160 ast_log(LOG_NOTICE
,"*** Link Name: %s ***\n",zl
->name
);
9161 ast_log(LOG_NOTICE
," link->lasttx %d\n",zl
->lasttx
);
9162 ast_log(LOG_NOTICE
," link->lastrx %d\n",zl
->lastrx
);
9163 ast_log(LOG_NOTICE
," link->connected %d\n",zl
->connected
);
9164 ast_log(LOG_NOTICE
," link->hasconnected %d\n",zl
->hasconnected
);
9165 ast_log(LOG_NOTICE
," link->outbound %d\n",zl
->outbound
);
9166 ast_log(LOG_NOTICE
," link->disced %d\n",zl
->disced
);
9167 ast_log(LOG_NOTICE
," link->killme %d\n",zl
->killme
);
9168 ast_log(LOG_NOTICE
," link->disctime %ld\n",zl
->disctime
);
9169 ast_log(LOG_NOTICE
," link->retrytimer %ld\n",zl
->retrytimer
);
9170 ast_log(LOG_NOTICE
," link->retries = %d\n",zl
->retries
);
9171 ast_log(LOG_NOTICE
," link->reconnects = %d\n",zl
->reconnects
);
9175 zt
= myrpt
->tele
.next
;
9176 if(zt
!= &myrpt
->tele
)
9177 ast_log(LOG_NOTICE
,"*** Telemetry Queue ***\n");
9178 while(zt
!= &myrpt
->tele
){
9179 ast_log(LOG_NOTICE
," Telemetry mode: %d\n",zt
->mode
);
9182 ast_log(LOG_NOTICE
,"******* Variable Dump End (app_rpt) *******\n");
9189 struct rpt_tele
*telem
;
9191 rpt_mutex_lock(&myrpt
->lock
);
9192 telem
= myrpt
->tele
.next
;
9193 while(telem
!= &myrpt
->tele
)
9195 ast_softhangup(telem
->chan
,AST_SOFTHANGUP_DEV
);
9196 telem
= telem
->next
;
9199 rpt_mutex_unlock(&myrpt
->lock
);
9201 /* find our index, and load the vars */
9202 for(i
= 0; i
< nrpts
; i
++)
9204 if (&rpt_vars
[i
] == myrpt
)
9212 rpt_mutex_lock(&myrpt
->lock
);
9213 if (ast_check_hangup(myrpt
->rxchannel
)) break;
9214 if (ast_check_hangup(myrpt
->txchannel
)) break;
9215 if (ast_check_hangup(myrpt
->pchannel
)) break;
9216 if (ast_check_hangup(myrpt
->monchannel
)) break;
9217 if (ast_check_hangup(myrpt
->txpchannel
)) break;
9218 if (myrpt
->zaptxchannel
&& ast_check_hangup(myrpt
->zaptxchannel
)) break;
9220 /* Set local tx with keyed */
9221 myrpt
->localtx
= myrpt
->keyed
;
9222 /* If someone's connected, and they're transmitting from their end to us, set remrx true */
9223 l
= myrpt
->links
.next
;
9225 while(l
!= &myrpt
->links
)
9229 if(l
->name
[0] != '0') /* Ignore '0' nodes */
9230 strcpy(myrpt
->lastnodewhichkeyedusup
, l
->name
); /* Note the node which is doing the key up */
9234 /* Create a "must_id" flag for the cleanup ID */
9235 if(myrpt
->p
.idtime
) /* ID time must be non-zero */
9236 myrpt
->mustid
|= (myrpt
->idtimer
) && (myrpt
->keyed
|| remrx
) ;
9237 /* Build a fresh totx from myrpt->keyed and autopatch activated */
9238 totx
= myrpt
->callmode
;
9239 /* If full duplex, add local tx to totx */
9240 if (myrpt
->p
.duplex
> 1)
9242 totx
= totx
|| myrpt
->localtx
;
9244 /* Traverse the telemetry list to see what's queued */
9246 othertelemqueued
= 0;
9247 tailmessagequeued
= 0;
9249 telem
= myrpt
->tele
.next
;
9250 while(telem
!= &myrpt
->tele
)
9252 if((telem
->mode
== ID
) || (telem
->mode
== IDTALKOVER
)){
9253 identqueued
= 1; /* Identification telemetry */
9255 else if(telem
->mode
== TAILMSG
)
9257 tailmessagequeued
= 1; /* Tail message telemetry */
9261 if ((telem
->mode
!= UNKEY
) && (telem
->mode
!= LINKUNKEY
))
9262 othertelemqueued
= 1; /* Other telemetry */
9264 ctqueued
= 1; /* Courtesy tone telemetry */
9266 telem
= telem
->next
;
9269 /* Add in any "other" telemetry, unless specified otherwise */
9270 if (!myrpt
->p
.notelemtx
) totx
= totx
|| othertelemqueued
;
9271 /* Update external (to links) transmitter PTT state with everything but ID, CT, and tailmessage telemetry */
9272 myrpt
->exttx
= totx
;
9273 totx
= totx
|| myrpt
->dtmf_local_timer
;
9274 /* If half or 3/4 duplex, add localtx to external link tx */
9275 if (myrpt
->p
.duplex
< 2) myrpt
->exttx
= myrpt
->exttx
|| myrpt
->localtx
;
9276 /* Add in ID telemetry to local transmitter */
9277 totx
= totx
|| remrx
;
9278 /* If 3/4 or full duplex, add in ident and CT telemetry */
9279 if (myrpt
->p
.duplex
> 0)
9280 totx
= totx
|| identqueued
|| ctqueued
;
9281 /* If full duplex, add local dtmf stuff active */
9282 if (myrpt
->p
.duplex
> 1)
9284 totx
= totx
|| (myrpt
->dtmfidx
> -1) ||
9287 /* Reset time out timer variables if there is no activity */
9290 myrpt
->totimer
= myrpt
->p
.totime
;
9291 myrpt
->tounkeyed
= 0;
9292 myrpt
->tonotify
= 0;
9295 myrpt
->tailtimer
= myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].alternatetail
?
9296 myrpt
->p
.althangtime
: /* Initialize tail timer */
9299 /* Disable the local transmitter if we are timed out */
9300 totx
= totx
&& myrpt
->totimer
;
9301 /* if timed-out and not said already, say it */
9302 if ((!myrpt
->totimer
) && (!myrpt
->tonotify
))
9304 myrpt
->tonotify
= 1;
9306 rpt_mutex_unlock(&myrpt
->lock
);
9307 rpt_telemetry(myrpt
,TIMEOUT
,NULL
);
9308 rpt_mutex_lock(&myrpt
->lock
);
9311 /* If unkey and re-key, reset time out timer */
9312 if ((!totx
) && (!myrpt
->totimer
) && (!myrpt
->tounkeyed
) && (!myrpt
->keyed
))
9314 myrpt
->tounkeyed
= 1;
9316 if ((!totx
) && (!myrpt
->totimer
) && myrpt
->tounkeyed
&& myrpt
->keyed
)
9318 myrpt
->totimer
= myrpt
->p
.totime
;
9319 myrpt
->tounkeyed
= 0;
9320 myrpt
->tonotify
= 0;
9321 rpt_mutex_unlock(&myrpt
->lock
);
9324 /* if timed-out and in circuit busy after call */
9325 if ((!totx
) && (!myrpt
->totimer
) && (myrpt
->callmode
== 4))
9327 myrpt
->callmode
= 0;
9329 /* get rid of tail if timed out */
9330 if (!myrpt
->totimer
) myrpt
->tailtimer
= 0;
9331 /* if not timed-out, add in tail */
9332 if (myrpt
->totimer
) totx
= totx
|| myrpt
->tailtimer
;
9333 /* If user or links key up or are keyed up over standard ID, switch to talkover ID, if one is defined */
9334 /* If tail message, kill the message if someone keys up over it */
9335 if ((myrpt
->keyed
|| remrx
) && ((identqueued
&& idtalkover
) || (tailmessagequeued
))) {
9336 int hasid
= 0,hastalkover
= 0;
9338 telem
= myrpt
->tele
.next
;
9339 while(telem
!= &myrpt
->tele
){
9340 if(telem
->mode
== ID
){
9341 if (telem
->chan
) ast_softhangup(telem
->chan
, AST_SOFTHANGUP_DEV
); /* Whoosh! */
9344 if(telem
->mode
== TAILMSG
){
9345 if (telem
->chan
) ast_softhangup(telem
->chan
, AST_SOFTHANGUP_DEV
); /* Whoosh! */
9347 if (telem
->mode
== IDTALKOVER
) hastalkover
= 1;
9348 telem
= telem
->next
;
9350 rpt_mutex_unlock(&myrpt
->lock
);
9351 if (hasid
&& (!hastalkover
)) rpt_telemetry(myrpt
, IDTALKOVER
, NULL
); /* Start Talkover ID */
9352 rpt_mutex_lock(&myrpt
->lock
);
9354 /* Try to be polite */
9355 /* If the repeater has been inactive for longer than the ID time, do an initial ID in the tail*/
9356 /* If within 30 seconds of the time to ID, try do it in the tail */
9357 /* else if at ID time limit, do it right over the top of them */
9358 /* Lastly, if the repeater has been keyed, and the ID timer is expired, do a clean up ID */
9359 if(myrpt
->mustid
&& (!myrpt
->idtimer
))
9362 if ((myrpt
->p
.idtime
&& totx
&& (!myrpt
->exttx
) &&
9363 (myrpt
->idtimer
<= myrpt
->p
.politeid
) && myrpt
->tailtimer
)) /* ID time must be non-zero */
9368 /* If tail timer expires, then check for tail messages */
9370 if(myrpt
->tailevent
){
9371 myrpt
->tailevent
= 0;
9376 else if ((myrpt
->p
.tailmessages
[0]) &&
9377 (myrpt
->p
.tailmessagetime
) && (myrpt
->tmsgtimer
== 0)){
9379 myrpt
->tmsgtimer
= myrpt
->p
.tailmessagetime
;
9380 rpt_mutex_unlock(&myrpt
->lock
);
9381 rpt_telemetry(myrpt
, TAILMSG
, NULL
);
9382 rpt_mutex_lock(&myrpt
->lock
);
9386 /* Main TX control */
9388 /* let telemetry transmit anyway (regardless of timeout) */
9389 if (myrpt
->p
.duplex
> 0) totx
= totx
|| (myrpt
->tele
.next
!= &myrpt
->tele
);
9390 if (totx
&& (!lasttx
))
9392 char mydate
[100],myfname
[100];
9395 if (myrpt
->monstream
) ast_closestream(myrpt
->monstream
);
9396 if (myrpt
->p
.archivedir
)
9401 strftime(mydate
,sizeof(mydate
) - 1,"%Y%m%d%H%M%S",
9403 sprintf(myfname
,"%s/%s/%s",myrpt
->p
.archivedir
,
9404 myrpt
->name
,mydate
);
9405 myrpt
->monstream
= ast_writefile(myfname
,"wav49",
9406 "app_rpt Air Archive",O_CREAT
| O_APPEND
,0,0600);
9407 if (myrpt
->p
.monminblocks
)
9409 blocksleft
= diskavail(myrpt
);
9410 if (blocksleft
>= myrpt
->p
.monminblocks
)
9411 donodelog(myrpt
,"TXKEY,MAIN");
9412 } else donodelog(myrpt
,"TXKEY,MAIN");
9415 myrpt
->dailykeyups
++;
9416 myrpt
->totalkeyups
++;
9417 rpt_mutex_unlock(&myrpt
->lock
);
9418 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_KEY
);
9419 rpt_mutex_lock(&myrpt
->lock
);
9421 totx
= totx
&& !myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
;
9422 if ((!totx
) && lasttx
)
9424 if (myrpt
->monstream
) ast_closestream(myrpt
->monstream
);
9425 myrpt
->monstream
= NULL
;
9428 rpt_mutex_unlock(&myrpt
->lock
);
9429 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_UNKEY
);
9430 rpt_mutex_lock(&myrpt
->lock
);
9431 donodelog(myrpt
,"TXUNKEY,MAIN");
9434 /* if DTMF timeout */
9435 if ((!myrpt
->cmdnode
[0]) && (myrpt
->dtmfidx
>= 0) && ((myrpt
->dtmf_time
+ DTMF_TIMEOUT
) < t
))
9437 myrpt
->dtmfidx
= -1;
9438 myrpt
->dtmfbuf
[0] = 0;
9440 /* if remote DTMF timeout */
9441 if ((myrpt
->rem_dtmfidx
>= 0) && ((myrpt
->rem_dtmf_time
+ DTMF_TIMEOUT
) < t
))
9443 myrpt
->rem_dtmfidx
= -1;
9444 myrpt
->rem_dtmfbuf
[0] = 0;
9449 l
= myrpt
->links
.next
;
9450 while(l
!= &myrpt
->links
)
9454 /* remove from queue */
9455 remque((struct qelem
*) l
);
9456 if (!strcmp(myrpt
->cmdnode
,l
->name
))
9457 myrpt
->cmdnode
[0] = 0;
9458 rpt_mutex_unlock(&myrpt
->lock
);
9459 /* hang-up on call to device */
9460 if (l
->chan
) ast_hangup(l
->chan
);
9461 ast_hangup(l
->pchan
);
9463 rpt_mutex_lock(&myrpt
->lock
);
9464 /* re-start link traversal */
9465 l
= myrpt
->links
.next
;
9471 cs
[n
++] = myrpt
->rxchannel
;
9472 cs
[n
++] = myrpt
->pchannel
;
9473 cs
[n
++] = myrpt
->monchannel
;
9474 cs
[n
++] = myrpt
->txpchannel
;
9475 if (myrpt
->txchannel
!= myrpt
->rxchannel
) cs
[n
++] = myrpt
->txchannel
;
9476 if (myrpt
->zaptxchannel
!= myrpt
->txchannel
)
9477 cs
[n
++] = myrpt
->zaptxchannel
;
9478 l
= myrpt
->links
.next
;
9479 while(l
!= &myrpt
->links
)
9481 if ((!l
->killme
) && (!l
->disctime
) && l
->chan
)
9488 rpt_mutex_unlock(&myrpt
->lock
);
9490 for(x
= 0; x
< n
; x
++)
9492 int s
= -(-x
- myrpt
->scram
- 1) % n
;
9496 who
= ast_waitfor_n(cs1
,n
,&ms
);
9497 if (who
== NULL
) ms
= 0;
9499 rpt_mutex_lock(&myrpt
->lock
);
9500 l
= myrpt
->links
.next
;
9501 while(l
!= &myrpt
->links
)
9503 if (l
->linklisttimer
)
9505 l
->linklisttimer
-= elap
;
9506 if (l
->linklisttimer
< 0) l
->linklisttimer
= 0;
9508 if ((!l
->linklisttimer
) && (l
->name
[0] != '0') && (!l
->isremote
))
9510 struct ast_frame lf
;
9512 memset(&lf
,0,sizeof(lf
));
9513 lf
.frametype
= AST_FRAME_TEXT
;
9518 l
->linklisttimer
= LINKLISTTIME
;
9520 __mklinklist(myrpt
,l
,lstr
+ 2);
9523 lf
.datalen
= strlen(lstr
) + 1;
9525 ast_write(l
->chan
,&lf
);
9526 if (debug
> 6) ast_log(LOG_NOTICE
,
9527 "@@@@ node %s sent node string %s to node %s\n",
9528 myrpt
->name
,lstr
,l
->name
);
9532 if ((l
->retxtimer
+= elap
) >= REDUNDANT_TX_TIME
)
9535 if (l
->chan
&& l
->phonemode
== 0)
9538 ast_indicate(l
->chan
,AST_CONTROL_RADIO_KEY
);
9540 ast_indicate(l
->chan
,AST_CONTROL_RADIO_UNKEY
);
9543 if ((l
->rerxtimer
+= elap
) >= (REDUNDANT_TX_TIME
* 5))
9545 if (debug
== 7) printf("@@@@ rx un-key\n");
9549 rpt_telemetry(myrpt
,LINKUNKEY
,l
);
9550 if (myrpt
->p
.archivedir
)
9555 sprintf(str
,"RXUNKEY(T),%s",l
->name
);
9556 donodelog(myrpt
,str
);
9560 if (l
->disctime
) /* Disconnect timer active on a channel ? */
9562 l
->disctime
-= elap
;
9563 if (l
->disctime
<= 0) /* Disconnect timer expired on inbound channel ? */
9564 l
->disctime
= 0; /* Yep */
9569 l
->retrytimer
-= elap
;
9570 if (l
->retrytimer
< 0) l
->retrytimer
= 0;
9573 /* Tally connect time */
9574 l
->connecttime
+= elap
;
9576 /* ignore non-timing channels */
9577 if (l
->elaptime
< 0)
9582 l
->elaptime
+= elap
;
9583 /* if connection has taken too long */
9584 if ((l
->elaptime
> MAXCONNECTTIME
) &&
9585 ((!l
->chan
) || (l
->chan
->_state
!= AST_STATE_UP
)))
9588 rpt_mutex_unlock(&myrpt
->lock
);
9589 if (l
->chan
) ast_softhangup(l
->chan
,AST_SOFTHANGUP_DEV
);
9590 rpt_mutex_lock(&myrpt
->lock
);
9593 if ((!l
->chan
) && (!l
->retrytimer
) && l
->outbound
&&
9594 (l
->retries
++ < l
->max_retries
) && (l
->hasconnected
))
9596 if (l
->chan
) ast_hangup(l
->chan
);
9598 rpt_mutex_unlock(&myrpt
->lock
);
9599 if ((l
->name
[0] != '0') && (!l
->isremote
))
9601 if (attempt_reconnect(myrpt
,l
) == -1)
9603 l
->retrytimer
= RETRY_TIMER_MS
;
9608 l
->retrytimer
= l
->max_retries
+ 1;
9611 rpt_mutex_lock(&myrpt
->lock
);
9614 if ((!l
->chan
) && (!l
->retrytimer
) && l
->outbound
&&
9615 (l
->retries
>= l
->max_retries
))
9617 /* remove from queue */
9618 remque((struct qelem
*) l
);
9619 if (!strcmp(myrpt
->cmdnode
,l
->name
))
9620 myrpt
->cmdnode
[0] = 0;
9621 rpt_mutex_unlock(&myrpt
->lock
);
9622 if (l
->name
[0] != '0')
9624 if (!l
->hasconnected
)
9625 rpt_telemetry(myrpt
,CONNFAIL
,l
);
9626 else rpt_telemetry(myrpt
,REMDISC
,l
);
9628 if (myrpt
->p
.archivedir
)
9632 if (!l
->hasconnected
)
9633 sprintf(str
,"LINKFAIL,%s",l
->name
);
9635 sprintf(str
,"LINKDISC,%s",l
->name
);
9636 donodelog(myrpt
,str
);
9638 /* hang-up on call to device */
9639 ast_hangup(l
->pchan
);
9641 rpt_mutex_lock(&myrpt
->lock
);
9644 if ((!l
->chan
) && (!l
->disctime
) && (!l
->outbound
))
9646 /* remove from queue */
9647 remque((struct qelem
*) l
);
9648 if (!strcmp(myrpt
->cmdnode
,l
->name
))
9649 myrpt
->cmdnode
[0] = 0;
9650 rpt_mutex_unlock(&myrpt
->lock
);
9651 if (l
->name
[0] != '0')
9653 rpt_telemetry(myrpt
,REMDISC
,l
);
9655 if (myrpt
->p
.archivedir
)
9659 sprintf(str
,"LINKDISC,%s",l
->name
);
9660 donodelog(myrpt
,str
);
9662 /* hang-up on call to device */
9663 ast_hangup(l
->pchan
);
9665 rpt_mutex_lock(&myrpt
->lock
);
9671 myrpt
->dailytxtime
+= elap
;
9672 myrpt
->totaltxtime
+= elap
;
9674 i
= myrpt
->tailtimer
;
9675 if (myrpt
->tailtimer
) myrpt
->tailtimer
-= elap
;
9676 if (myrpt
->tailtimer
< 0) myrpt
->tailtimer
= 0;
9677 if((i
) && (myrpt
->tailtimer
== 0))
9678 myrpt
->tailevent
= 1;
9679 if ((!myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].totdisable
) && myrpt
->totimer
) myrpt
->totimer
-= elap
;
9680 if (myrpt
->totimer
< 0) myrpt
->totimer
= 0;
9681 if (myrpt
->idtimer
) myrpt
->idtimer
-= elap
;
9682 if (myrpt
->idtimer
< 0) myrpt
->idtimer
= 0;
9683 if (myrpt
->tmsgtimer
) myrpt
->tmsgtimer
-= elap
;
9684 if (myrpt
->tmsgtimer
< 0) myrpt
->tmsgtimer
= 0;
9685 /* do macro timers */
9686 if (myrpt
->macrotimer
) myrpt
->macrotimer
-= elap
;
9687 if (myrpt
->macrotimer
< 0) myrpt
->macrotimer
= 0;
9688 /* do local dtmf timer */
9689 if (myrpt
->dtmf_local_timer
)
9691 if (myrpt
->dtmf_local_timer
> 1) myrpt
->dtmf_local_timer
-= elap
;
9692 if (myrpt
->dtmf_local_timer
< 1) myrpt
->dtmf_local_timer
= 1;
9694 do_dtmf_local(myrpt
,0);
9695 /* Execute scheduler appx. every 2 tenths of a second */
9696 if (myrpt
->skedtimer
<= 0){
9697 myrpt
->skedtimer
= 200;
9698 do_scheduler(myrpt
);
9701 myrpt
->skedtimer
-=elap
;
9704 rpt_mutex_unlock(&myrpt
->lock
);
9707 c
= myrpt
->macrobuf
[0];
9709 if (c
&& (!myrpt
->macrotimer
) &&
9710 starttime
&& (t
> (starttime
+ START_DELAY
)))
9712 myrpt
->macrotimer
= MACROTIME
;
9713 memmove(myrpt
->macrobuf
,myrpt
->macrobuf
+ 1,MAXMACRO
- 1);
9714 if ((c
== 'p') || (c
== 'P'))
9715 myrpt
->macrotimer
= MACROPTIME
;
9716 rpt_mutex_unlock(&myrpt
->lock
);
9717 if (myrpt
->p
.archivedir
)
9721 sprintf(str
,"DTMF(M),MAIN,%c",c
);
9722 donodelog(myrpt
,str
);
9724 local_dtmf_helper(myrpt
,c
);
9725 } else rpt_mutex_unlock(&myrpt
->lock
);
9726 if (who
== myrpt
->rxchannel
) /* if it was a read from rx */
9730 f
= ast_read(myrpt
->rxchannel
);
9733 if (debug
) printf("@@@@ rpt:Hung Up\n");
9736 if (f
->frametype
== AST_FRAME_VOICE
)
9738 #ifdef _MDC_DECODE_H_
9739 unsigned char ubuf
[2560];
9744 if ((!myrpt
->localtx
) && (!myrpt
->p
.linktolink
)) {
9745 memset(f
->data
,0,f
->datalen
);
9748 #ifdef _MDC_DECODE_H_
9749 sp
= (short *) f
->data
;
9750 /* convert block to unsigned char */
9751 for(n
= 0; n
< f
->datalen
/ 2; n
++)
9753 ubuf
[n
] = (*sp
++ >> 8) + 128;
9755 n
= mdc_decoder_process_samples(myrpt
->mdc
,ubuf
,f
->datalen
/ 2);
9758 unsigned char op
,arg
;
9759 unsigned short unitID
;
9761 mdc_decoder_get_packet(myrpt
->mdc
,&op
,&arg
,&unitID
);
9764 ast_log(LOG_NOTICE
,"Got (single-length) packet:\n");
9765 ast_log(LOG_NOTICE
,"op: %02x, arg: %02x, UnitID: %04x\n",
9766 op
& 255,arg
& 255,unitID
);
9768 if ((op
== 1) && (arg
== 0))
9770 myrpt
->lastunit
= unitID
;
9771 mdc1200_notify(myrpt
,NULL
,myrpt
->lastunit
);
9772 mdc1200_send(myrpt
,myrpt
->lastunit
);
9775 if ((debug
> 2) && (i
== 2))
9777 unsigned char op
,arg
,ex1
,ex2
,ex3
,ex4
;
9778 unsigned short unitID
;
9780 mdc_decoder_get_double_packet(myrpt
->mdc
,&op
,&arg
,&unitID
,
9781 &ex1
,&ex2
,&ex3
,&ex4
);
9782 ast_log(LOG_NOTICE
,"Got (double-length) packet:\n");
9783 ast_log(LOG_NOTICE
,"op: %02x, arg: %02x, UnitID: %04x\n",
9784 op
& 255,arg
& 255,unitID
);
9785 ast_log(LOG_NOTICE
,"ex1: %02x, ex2: %02x, ex3: %02x, ex4: %02x\n",
9786 ex1
& 255, ex2
& 255, ex3
& 255, ex4
& 255);
9790 /* apply inbound filters, if any */
9791 rpt_filter(myrpt
,f
->data
,f
->datalen
/ 2);
9793 if (ioctl(myrpt
->zaprxchannel
->fds
[0], ZT_GETCONFMUTE
, &ismuted
) == -1)
9797 if (dtmfed
) ismuted
= 1;
9801 memset(f
->data
,0,f
->datalen
);
9803 memset(myrpt
->lastf1
->data
,0,myrpt
->lastf1
->datalen
);
9805 memset(myrpt
->lastf2
->data
,0,myrpt
->lastf2
->datalen
);
9807 if (f
) f2
= ast_frdup(f
);
9810 myrpt
->lastf2
= myrpt
->lastf1
;
9815 memset(myrpt
->lastf1
->data
,0,myrpt
->lastf1
->datalen
);
9817 memset(myrpt
->lastf2
->data
,0,myrpt
->lastf2
->datalen
);
9821 ast_write(myrpt
->pchannel
,f1
);
9825 #ifndef OLD_ASTERISK
9826 else if (f
->frametype
== AST_FRAME_DTMF_BEGIN
)
9829 memset(myrpt
->lastf1
->data
,0,myrpt
->lastf1
->datalen
);
9831 memset(myrpt
->lastf2
->data
,0,myrpt
->lastf2
->datalen
);
9835 else if (f
->frametype
== AST_FRAME_DTMF
)
9837 c
= (char) f
->subclass
; /* get DTMF char */
9840 memset(myrpt
->lastf1
->data
,0,myrpt
->lastf1
->datalen
);
9842 memset(myrpt
->lastf2
->data
,0,myrpt
->lastf2
->datalen
);
9844 if (!myrpt
->keyed
) continue;
9845 c
= func_xlat(myrpt
,c
,&myrpt
->p
.inxlat
);
9846 if (c
) local_dtmf_helper(myrpt
,c
);
9849 else if (f
->frametype
== AST_FRAME_CONTROL
)
9851 if (f
->subclass
== AST_CONTROL_HANGUP
)
9853 if (debug
) printf("@@@@ rpt:Hung Up\n");
9858 if (f
->subclass
== AST_CONTROL_RADIO_KEY
)
9860 if ((!lasttx
) || (myrpt
->p
.duplex
> 1) || (myrpt
->p
.linktolink
))
9862 if (debug
== 7) printf("@@@@ rx key\n");
9865 if (myrpt
->p
.archivedir
)
9867 donodelog(myrpt
,"RXKEY,MAIN");
9871 if (f
->subclass
== AST_CONTROL_RADIO_UNKEY
)
9873 if ((!lasttx
) || (myrpt
->p
.duplex
> 1) || (myrpt
->p
.linktolink
))
9875 if (debug
== 7) printf("@@@@ rx un-key\n");
9876 if(myrpt
->p
.duplex
&& myrpt
->keyed
) {
9877 rpt_telemetry(myrpt
,UNKEY
,NULL
);
9881 if (myrpt
->p
.archivedir
)
9883 donodelog(myrpt
,"RXUNKEY,MAIN");
9890 if (who
== myrpt
->pchannel
) /* if it was a read from pseudo */
9892 f
= ast_read(myrpt
->pchannel
);
9895 if (debug
) printf("@@@@ rpt:Hung Up\n");
9898 if (f
->frametype
== AST_FRAME_VOICE
)
9900 ast_write(myrpt
->txpchannel
,f
);
9902 if (f
->frametype
== AST_FRAME_CONTROL
)
9904 if (f
->subclass
== AST_CONTROL_HANGUP
)
9906 if (debug
) printf("@@@@ rpt:Hung Up\n");
9914 if (who
== myrpt
->txchannel
) /* if it was a read from tx */
9916 f
= ast_read(myrpt
->txchannel
);
9919 if (debug
) printf("@@@@ rpt:Hung Up\n");
9922 if (f
->frametype
== AST_FRAME_CONTROL
)
9924 if (f
->subclass
== AST_CONTROL_HANGUP
)
9926 if (debug
) printf("@@@@ rpt:Hung Up\n");
9934 if (who
== myrpt
->zaptxchannel
) /* if it was a read from pseudo-tx */
9936 f
= ast_read(myrpt
->zaptxchannel
);
9939 if (debug
) printf("@@@@ rpt:Hung Up\n");
9942 if (f
->frametype
== AST_FRAME_VOICE
)
9944 ast_write(myrpt
->txchannel
,f
);
9946 if (f
->frametype
== AST_FRAME_CONTROL
)
9948 if (f
->subclass
== AST_CONTROL_HANGUP
)
9950 if (debug
) printf("@@@@ rpt:Hung Up\n");
9959 rpt_mutex_lock(&myrpt
->lock
);
9960 l
= myrpt
->links
.next
;
9961 while(l
!= &myrpt
->links
)
9968 if (who
== l
->chan
) /* if it was a read from rx */
9973 /* see if any other links are receiving */
9974 m
= myrpt
->links
.next
;
9975 while(m
!= &myrpt
->links
)
9977 /* if not us, count it */
9978 if ((m
!= l
) && (m
->lastrx
)) remrx
= 1;
9981 rpt_mutex_unlock(&myrpt
->lock
);
9982 remnomute
= myrpt
->localtx
&&
9983 (!(myrpt
->cmdnode
[0] ||
9984 (myrpt
->dtmfidx
> -1)));
9985 totx
= (((l
->isremote
) ? (remnomute
) :
9986 myrpt
->exttx
) || remrx
) && l
->mode
;
9987 if (l
->phonemode
== 0 && l
->chan
&& (l
->lasttx
!= totx
))
9991 ast_indicate(l
->chan
,AST_CONTROL_RADIO_KEY
);
9995 ast_indicate(l
->chan
,AST_CONTROL_RADIO_UNKEY
);
9997 if (myrpt
->p
.archivedir
)
10002 sprintf(str
,"TXKEY,%s",l
->name
);
10004 sprintf(str
,"TXUNKEY,%s",l
->name
);
10005 donodelog(myrpt
,str
);
10009 f
= ast_read(l
->chan
);
10012 rpt_mutex_lock(&myrpt
->lock
);
10013 __kickshort(myrpt
);
10014 rpt_mutex_unlock(&myrpt
->lock
);
10015 if ((!l
->disced
) && (!l
->outbound
))
10017 if ((l
->name
[0] == '0') || l
->isremote
)
10020 l
->disctime
= DISC_TIME
;
10021 rpt_mutex_lock(&myrpt
->lock
);
10022 ast_hangup(l
->chan
);
10029 ast_hangup(l
->chan
);
10031 rpt_mutex_lock(&myrpt
->lock
);
10034 if (l
->outbound
&& (l
->retries
++ < l
->max_retries
) && (l
->hasconnected
))
10036 rpt_mutex_lock(&myrpt
->lock
);
10037 if (l
->chan
) ast_hangup(l
->chan
);
10039 l
->hasconnected
= 1;
10040 l
->retrytimer
= RETRY_TIMER_MS
;
10042 l
->connecttime
= 0;
10043 l
->thisconnected
= 0;
10046 rpt_mutex_lock(&myrpt
->lock
);
10047 /* remove from queue */
10048 remque((struct qelem
*) l
);
10049 if (!strcmp(myrpt
->cmdnode
,l
->name
))
10050 myrpt
->cmdnode
[0] = 0;
10051 __kickshort(myrpt
);
10052 rpt_mutex_unlock(&myrpt
->lock
);
10053 if (!l
->hasconnected
)
10054 rpt_telemetry(myrpt
,CONNFAIL
,l
);
10055 else if (l
->disced
!= 2) rpt_telemetry(myrpt
,REMDISC
,l
);
10056 if (myrpt
->p
.archivedir
)
10060 if (!l
->hasconnected
)
10061 sprintf(str
,"LINKFAIL,%s",l
->name
);
10063 sprintf(str
,"LINKDISC,%s",l
->name
);
10064 donodelog(myrpt
,str
);
10066 if (l
->lastf1
) ast_frfree(l
->lastf1
);
10068 if (l
->lastf2
) ast_frfree(l
->lastf2
);
10070 /* hang-up on call to device */
10071 ast_hangup(l
->chan
);
10072 ast_hangup(l
->pchan
);
10074 rpt_mutex_lock(&myrpt
->lock
);
10077 if (f
->frametype
== AST_FRAME_VOICE
)
10083 if (ioctl(l
->chan
->fds
[0], ZT_GETCONFMUTE
, &ismuted
) == -1)
10087 /* if not receiving, zero-out audio */
10088 ismuted
|= (!l
->lastrx
);
10089 if (l
->dtmfed
&& l
->phonemode
) ismuted
= 1;
10093 memset(f
->data
,0,f
->datalen
);
10095 memset(l
->lastf1
->data
,0,l
->lastf1
->datalen
);
10097 memset(l
->lastf2
->data
,0,l
->lastf2
->datalen
);
10099 if (f
) f2
= ast_frdup(f
);
10102 l
->lastf2
= l
->lastf1
;
10107 memset(l
->lastf1
->data
,0,l
->lastf1
->datalen
);
10109 memset(l
->lastf2
->data
,0,l
->lastf2
->datalen
);
10113 ast_write(l
->pchan
,f1
);
10120 memset(f
->data
,0,f
->datalen
);
10121 ast_write(l
->pchan
,f
);
10124 #ifndef OLD_ASTERISK
10125 else if (f
->frametype
== AST_FRAME_DTMF_BEGIN
)
10128 memset(l
->lastf1
->data
,0,l
->lastf1
->datalen
);
10130 memset(l
->lastf2
->data
,0,l
->lastf2
->datalen
);
10135 if (f
->frametype
== AST_FRAME_TEXT
)
10137 handle_link_data(myrpt
,l
,f
->data
);
10139 if (f
->frametype
== AST_FRAME_DTMF
)
10142 memset(l
->lastf1
->data
,0,l
->lastf1
->datalen
);
10144 memset(l
->lastf2
->data
,0,l
->lastf2
->datalen
);
10146 handle_link_phone_dtmf(myrpt
,l
,f
->subclass
);
10148 if (f
->frametype
== AST_FRAME_CONTROL
)
10150 if (f
->subclass
== AST_CONTROL_ANSWER
)
10152 char lconnected
= l
->connected
;
10154 __kickshort(myrpt
);
10156 l
->hasconnected
= 1;
10157 l
->thisconnected
= 1;
10159 if (!l
->isremote
) l
->retries
= 0;
10162 rpt_telemetry(myrpt
,CONNECTED
,l
);
10163 if (myrpt
->p
.archivedir
)
10168 sprintf(str
,"LINKTRX,%s",l
->name
);
10170 sprintf(str
,"LINKMONITOR,%s",l
->name
);
10171 donodelog(myrpt
,str
);
10178 if (f
->subclass
== AST_CONTROL_RADIO_KEY
)
10180 if (debug
== 7 ) printf("@@@@ rx key\n");
10183 if (myrpt
->p
.archivedir
&& (!l
->lastrx1
))
10188 sprintf(str
,"RXKEY,%s",l
->name
);
10189 donodelog(myrpt
,str
);
10193 if (f
->subclass
== AST_CONTROL_RADIO_UNKEY
)
10195 if (debug
== 7) printf("@@@@ rx un-key\n");
10198 if(myrpt
->p
.duplex
)
10199 rpt_telemetry(myrpt
,LINKUNKEY
,l
);
10200 if (myrpt
->p
.archivedir
&& (l
->lastrx1
))
10205 sprintf(str
,"RXUNKEY,%s",l
->name
);
10206 donodelog(myrpt
,str
);
10209 if (f
->subclass
== AST_CONTROL_HANGUP
)
10212 rpt_mutex_lock(&myrpt
->lock
);
10213 __kickshort(myrpt
);
10214 rpt_mutex_unlock(&myrpt
->lock
);
10215 if ((!l
->outbound
) && (!l
->disced
))
10217 if ((l
->name
[0] == '0') || l
->isremote
)
10220 l
->disctime
= DISC_TIME
;
10221 rpt_mutex_lock(&myrpt
->lock
);
10222 ast_hangup(l
->chan
);
10228 if (l
->chan
) ast_hangup(l
->chan
);
10230 rpt_mutex_lock(&myrpt
->lock
);
10233 if (l
->outbound
&& (l
->retries
++ < l
->max_retries
) && (l
->hasconnected
))
10235 rpt_mutex_lock(&myrpt
->lock
);
10236 if (l
->chan
) ast_hangup(l
->chan
);
10238 l
->hasconnected
= 1;
10240 l
->retrytimer
= RETRY_TIMER_MS
;
10241 l
->connecttime
= 0;
10242 l
->thisconnected
= 0;
10245 rpt_mutex_lock(&myrpt
->lock
);
10246 /* remove from queue */
10247 remque((struct qelem
*) l
);
10248 if (!strcmp(myrpt
->cmdnode
,l
->name
))
10249 myrpt
->cmdnode
[0] = 0;
10250 __kickshort(myrpt
);
10251 rpt_mutex_unlock(&myrpt
->lock
);
10252 if (!l
->hasconnected
)
10253 rpt_telemetry(myrpt
,CONNFAIL
,l
);
10254 else if (l
->disced
!= 2) rpt_telemetry(myrpt
,REMDISC
,l
);
10255 if (myrpt
->p
.archivedir
)
10259 if (!l
->hasconnected
)
10260 sprintf(str
,"LINKFAIL,%s",l
->name
);
10262 sprintf(str
,"LINKDISC,%s",l
->name
);
10263 donodelog(myrpt
,str
);
10265 if (l
->lastf1
) ast_frfree(l
->lastf1
);
10267 if (l
->lastf2
) ast_frfree(l
->lastf2
);
10269 /* hang-up on call to device */
10270 ast_hangup(l
->chan
);
10271 ast_hangup(l
->pchan
);
10273 rpt_mutex_lock(&myrpt
->lock
);
10278 rpt_mutex_lock(&myrpt
->lock
);
10281 if (who
== l
->pchan
)
10283 rpt_mutex_unlock(&myrpt
->lock
);
10284 f
= ast_read(l
->pchan
);
10287 if (debug
) printf("@@@@ rpt:Hung Up\n");
10289 rpt_mutex_lock(&myrpt
->lock
);
10292 if (f
->frametype
== AST_FRAME_VOICE
)
10294 if (l
->chan
) ast_write(l
->chan
,f
);
10296 if (f
->frametype
== AST_FRAME_CONTROL
)
10298 if (f
->subclass
== AST_CONTROL_HANGUP
)
10300 if (debug
) printf("@@@@ rpt:Hung Up\n");
10303 rpt_mutex_lock(&myrpt
->lock
);
10308 rpt_mutex_lock(&myrpt
->lock
);
10313 rpt_mutex_unlock(&myrpt
->lock
);
10315 if (who
== myrpt
->monchannel
)
10317 f
= ast_read(myrpt
->monchannel
);
10320 if (debug
) printf("@@@@ rpt:Hung Up\n");
10323 if (f
->frametype
== AST_FRAME_VOICE
)
10325 if (myrpt
->monstream
)
10326 ast_writestream(myrpt
->monstream
,f
);
10328 if (f
->frametype
== AST_FRAME_CONTROL
)
10330 if (f
->subclass
== AST_CONTROL_HANGUP
)
10332 if (debug
) printf("@@@@ rpt:Hung Up\n");
10340 if (who
== myrpt
->txpchannel
) /* if it was a read from remote tx */
10342 f
= ast_read(myrpt
->txpchannel
);
10345 if (debug
) printf("@@@@ rpt:Hung Up\n");
10348 if (f
->frametype
== AST_FRAME_CONTROL
)
10350 if (f
->subclass
== AST_CONTROL_HANGUP
)
10352 if (debug
) printf("@@@@ rpt:Hung Up\n");
10362 ast_hangup(myrpt
->pchannel
);
10363 ast_hangup(myrpt
->monchannel
);
10364 ast_hangup(myrpt
->txpchannel
);
10365 if (myrpt
->txchannel
!= myrpt
->rxchannel
) ast_hangup(myrpt
->txchannel
);
10366 if (myrpt
->zaptxchannel
!= myrpt
->txchannel
) ast_hangup(myrpt
->zaptxchannel
);
10367 if (myrpt
->lastf1
) ast_frfree(myrpt
->lastf1
);
10368 myrpt
->lastf1
= NULL
;
10369 if (myrpt
->lastf2
) ast_frfree(myrpt
->lastf2
);
10370 myrpt
->lastf2
= NULL
;
10371 ast_hangup(myrpt
->rxchannel
);
10372 rpt_mutex_lock(&myrpt
->lock
);
10373 l
= myrpt
->links
.next
;
10374 while(l
!= &myrpt
->links
)
10376 struct rpt_link
*ll
= l
;
10377 /* remove from queue */
10378 remque((struct qelem
*) l
);
10379 /* hang-up on call to device */
10380 if (l
->chan
) ast_hangup(l
->chan
);
10381 ast_hangup(l
->pchan
);
10385 rpt_mutex_unlock(&myrpt
->lock
);
10386 if (debug
) printf("@@@@ rpt:Hung up channel\n");
10387 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
10388 pthread_exit(NULL
);
10393 static void *rpt_master(void *ignore
)
10396 pthread_attr_t attr
;
10397 struct ast_config
*cfg
;
10400 /* init nodelog queue */
10401 nodelog
.next
= nodelog
.prev
= &nodelog
;
10402 /* go thru all the specified repeaters */
10405 /* wait until asterisk starts */
10406 while(!ast_test_flag(&ast_options
,AST_OPT_FLAG_FULLY_BOOTED
))
10408 rpt_vars
[n
].cfg
= ast_config_load("rpt.conf");
10409 cfg
= rpt_vars
[n
].cfg
;
10411 ast_log(LOG_NOTICE
, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
10412 pthread_exit(NULL
);
10414 while((this = ast_category_browse(cfg
,this)) != NULL
)
10416 for(i
= 0 ; i
< strlen(this) ; i
++){
10417 if((this[i
] < '0') || (this[i
] > '9'))
10420 if(i
!= strlen(this)) continue; /* Not a node defn */
10421 memset(&rpt_vars
[n
],0,sizeof(rpt_vars
[n
]));
10422 rpt_vars
[n
].name
= strdup(this);
10423 val
= (char *) ast_variable_retrieve(cfg
,this,"rxchannel");
10424 if (val
) rpt_vars
[n
].rxchanname
= strdup(val
);
10425 val
= (char *) ast_variable_retrieve(cfg
,this,"txchannel");
10426 if (val
) rpt_vars
[n
].txchanname
= strdup(val
);
10427 val
= (char *) ast_variable_retrieve(cfg
,this,"remote");
10428 if (val
) rpt_vars
[n
].remote
= strdup(val
);
10429 ast_mutex_init(&rpt_vars
[n
].lock
);
10430 ast_mutex_init(&rpt_vars
[n
].remlock
);
10431 rpt_vars
[n
].tele
.next
= &rpt_vars
[n
].tele
;
10432 rpt_vars
[n
].tele
.prev
= &rpt_vars
[n
].tele
;
10433 rpt_vars
[n
].rpt_thread
= AST_PTHREADT_NULL
;
10434 rpt_vars
[n
].tailmessagen
= 0;
10435 #ifdef _MDC_DECODE_H_
10436 rpt_vars
[n
].mdc
= mdc_decoder_new(8000);
10441 ast_config_destroy(cfg
);
10444 for(i
= 0; i
< n
; i
++)
10446 load_rpt_vars(i
,1);
10448 /* if is a remote, dont start one for it */
10449 if (rpt_vars
[i
].remote
)
10451 if(retreive_memory(&rpt_vars
[i
],"init")){ /* Try to retreive initial memory channel */
10452 strncpy(rpt_vars
[i
].freq
, "146.580", sizeof(rpt_vars
[i
].freq
) - 1);
10453 strncpy(rpt_vars
[i
].rxpl
, "100.0", sizeof(rpt_vars
[i
].rxpl
) - 1);
10455 strncpy(rpt_vars
[i
].txpl
, "100.0", sizeof(rpt_vars
[i
].txpl
) - 1);
10456 rpt_vars
[i
].remmode
= REM_MODE_FM
;
10457 rpt_vars
[i
].offset
= REM_SIMPLEX
;
10458 rpt_vars
[i
].powerlevel
= REM_MEDPWR
;
10462 if (!rpt_vars
[i
].p
.ident
)
10464 ast_log(LOG_WARNING
,"Did not specify ident for node %s\n",rpt_vars
[i
].name
);
10465 ast_config_destroy(cfg
);
10466 pthread_exit(NULL
);
10468 pthread_attr_init(&attr
);
10469 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
10470 ast_pthread_create(&rpt_vars
[i
].rpt_thread
,&attr
,rpt
,(void *) &rpt_vars
[i
]);
10476 /* Now monitor each thread, and restart it if necessary */
10477 for(i
= 0; i
< n
; i
++)
10480 if (rpt_vars
[i
].remote
) continue;
10481 if (rpt_vars
[i
].rpt_thread
== AST_PTHREADT_STOP
)
10484 rv
= pthread_kill(rpt_vars
[i
].rpt_thread
,0);
10487 if(time(NULL
) - rpt_vars
[i
].lastthreadrestarttime
<= 15)
10489 if(rpt_vars
[i
].threadrestarts
>= 5)
10491 ast_log(LOG_ERROR
,"Continual RPT thread restarts, killing Asterisk\n");
10492 exit(1); /* Stuck in a restart loop, kill Asterisk and start over */
10496 ast_log(LOG_NOTICE
,"RPT thread restarted on %s\n",rpt_vars
[i
].name
);
10497 rpt_vars
[i
].threadrestarts
++;
10501 rpt_vars
[i
].threadrestarts
= 0;
10503 rpt_vars
[i
].lastthreadrestarttime
= time(NULL
);
10504 pthread_attr_init(&attr
);
10505 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
10506 ast_pthread_create(&rpt_vars
[i
].rpt_thread
,&attr
,rpt
,(void *) &rpt_vars
[i
]);
10507 ast_log(LOG_WARNING
, "rpt_thread restarted on node %s\n", rpt_vars
[i
].name
);
10513 struct nodelog
*nodep
;
10514 char *space
,datestr
[100],fname
[300];
10517 ast_mutex_lock(&nodeloglock
);
10518 nodep
= nodelog
.next
;
10519 if(nodep
== &nodelog
) /* if nothing in queue */
10521 ast_mutex_unlock(&nodeloglock
);
10524 remque((struct qelem
*)nodep
);
10525 ast_mutex_unlock(&nodeloglock
);
10526 space
= strchr(nodep
->str
,' ');
10533 strftime(datestr
,sizeof(datestr
) - 1,"%Y%m%d",
10534 localtime(&nodep
->timestamp
));
10535 sprintf(fname
,"%s/%s/%s.txt",nodep
->archivedir
,
10536 nodep
->str
,datestr
);
10537 fd
= open(fname
,O_WRONLY
| O_CREAT
| O_APPEND
,0600);
10540 ast_log(LOG_ERROR
,"Cannot open node log file %s for write",space
+ 1);
10544 if (write(fd
,space
+ 1,strlen(space
+ 1)) !=
10547 ast_log(LOG_ERROR
,"Cannot write node log file %s for write",space
+ 1);
10556 ast_config_destroy(cfg
);
10557 pthread_exit(NULL
);
10560 static int rpt_exec(struct ast_channel
*chan
, void *data
)
10562 int res
=-1,i
,rem_totx
,rem_rx
,remkeyed
,n
,phone_mode
= 0;
10563 int iskenwood_pci4
,authtold
,authreq
,setting
,notremming
,reming
;
10564 int ismuted
,dtmfed
;
10565 #ifdef OLD_ASTERISK
10566 struct localuser
*u
;
10568 char tmp
[256], keyed
= 0,keyed1
= 0;
10569 char *options
,*stringp
,*tele
,c
;
10571 struct ast_frame
*f
,*f1
,*f2
;
10572 struct ast_channel
*who
;
10573 struct ast_channel
*cs
[20];
10574 struct rpt_link
*l
;
10575 ZT_CONFINFO ci
; /* conference info */
10577 int ms
,elap
,nullfd
;
10578 time_t t
,last_timeout_warning
;
10579 struct zt_radio_param z
;
10580 struct rpt_tele
*telem
;
10582 nullfd
= open("/dev/null",O_RDWR
);
10583 if (ast_strlen_zero(data
)) {
10584 ast_log(LOG_WARNING
, "Rpt requires an argument (system node)\n");
10588 strncpy(tmp
, (char *)data
, sizeof(tmp
)-1);
10590 /* if time has externally shifted negative, screw it */
10591 if (t
< starttime
) t
= starttime
+ START_DELAY
;
10592 if ((!starttime
) || (t
< (starttime
+ START_DELAY
)))
10594 ast_log(LOG_NOTICE
,"Node %s rejecting call: too soon!\n",tmp
);
10595 ast_safe_sleep(chan
,3000);
10599 strsep(&stringp
, "|");
10602 /* see if we can find our specified one */
10603 for(i
= 0; i
< nrpts
; i
++)
10605 /* if name matches, assign it and exit loop */
10606 if (!strcmp(tmp
,rpt_vars
[i
].name
))
10608 myrpt
= &rpt_vars
[i
];
10614 ast_log(LOG_WARNING
, "Cannot find specified system node %s\n",tmp
);
10618 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
){ /* Do not allow incoming connections if disabled */
10619 ast_log(LOG_NOTICE
, "Connect attempt to node %s with tx disabled", myrpt
->name
);
10623 /* if not phone access, must be an IAX connection */
10624 if (options
&& ((*options
== 'P') || (*options
== 'D') || (*options
== 'R')))
10629 if (*options
== 'D') phone_mode
= 2;
10630 ast_set_callerid(chan
,"0","app_rpt user","0");
10632 ast_channel_setoption(chan
,AST_OPTION_TONE_VERIFY
,&val
,sizeof(char),0);
10636 #ifdef ALLOW_LOCAL_CHANNELS
10637 /* Check to insure the connection is IAX2 or Local*/
10638 if ( (strncmp(chan
->name
,"IAX2",4)) && (strncmp(chan
->name
,"Local",5)) ) {
10639 ast_log(LOG_WARNING
, "We only accept links via IAX2 or Local!!\n");
10643 if (strncmp(chan
->name
,"IAX2",4))
10645 ast_log(LOG_WARNING
, "We only accept links via IAX2!!\n");
10650 if (options
&& (*options
== 'R'))
10653 /* Parts of this section taken from app_parkandannounce */
10654 char *return_context
;
10655 int l
, m
, lot
, timeout
= 0;
10656 char tmp
[256],*template;
10657 char *working
, *context
, *exten
, *priority
;
10661 rpt_mutex_lock(&myrpt
->lock
);
10662 m
= myrpt
->callmode
;
10663 rpt_mutex_unlock(&myrpt
->lock
);
10665 if ((!myrpt
->p
.nobusyout
) && m
)
10667 if (chan
->_state
!= AST_STATE_UP
)
10669 ast_indicate(chan
,AST_CONTROL_BUSY
);
10671 while(ast_safe_sleep(chan
,10000) != -1);
10675 if (chan
->_state
!= AST_STATE_UP
)
10680 l
=strlen(options
)+2;
10683 ast_log(LOG_WARNING
, "Out of memory\n");
10687 strncpy(s
,options
,l
);
10689 template=strsep(&s
,"|");
10691 ast_log(LOG_WARNING
, "An announce template must be defined\n");
10697 timeout
= atoi(strsep(&s
, "|"));
10701 return_context
= s
;
10703 if(return_context
!= NULL
) {
10704 /* set the return context. Code borrowed from the Goto builtin */
10706 working
= return_context
;
10707 context
= strsep(&working
, "|");
10708 exten
= strsep(&working
, "|");
10710 /* Only a priority in this one */
10711 priority
= context
;
10715 priority
= strsep(&working
, "|");
10717 /* Only an extension and priority in this one */
10723 if(atoi(priority
) < 0) {
10724 ast_log(LOG_WARNING
, "Priority '%s' must be a number > 0\n", priority
);
10728 /* At this point we have a priority and maybe an extension and a context */
10729 chan
->priority
= atoi(priority
);
10730 #ifdef OLD_ASTERISK
10731 if(exten
&& strcasecmp(exten
, "BYEXTENSION"))
10735 strncpy(chan
->exten
, exten
, sizeof(chan
->exten
)-1);
10737 strncpy(chan
->context
, context
, sizeof(chan
->context
)-1);
10738 } else { /* increment the priority by default*/
10742 if(option_verbose
> 2) {
10743 ast_verbose( VERBOSE_PREFIX_3
"Return Context: (%s,%s,%d) ID: %s\n", chan
->context
,chan
->exten
, chan
->priority
, chan
->cid
.cid_num
);
10744 if(!ast_exists_extension(chan
, chan
->context
, chan
->exten
, chan
->priority
, chan
->cid
.cid_num
)) {
10745 ast_verbose( VERBOSE_PREFIX_3
"Warning: Return Context Invalid, call will return to default|s\n");
10749 /* we are using masq_park here to protect * from touching the channel once we park it. If the channel comes out of timeout
10750 before we are done announcing and the channel is messed with, Kablooeee. So we use Masq to prevent this. */
10752 ast_masq_park_call(chan
, NULL
, timeout
, &lot
);
10754 if (option_verbose
> 2) ast_verbose( VERBOSE_PREFIX_3
"Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot
, timeout
, return_context
);
10756 snprintf(tmp
,sizeof(tmp
) - 1,"%d,%s",lot
,template + 1);
10758 rpt_telemetry(myrpt
,REV_PATCH
,tmp
);
10768 struct ast_hostent ahp
;
10769 struct hostent
*hp
;
10771 char hisip
[100],nodeip
[100],*val
, *s
, *s1
, *s2
, *b
,*b1
;
10773 /* look at callerid to see what node this comes from */
10774 if (!chan
->cid
.cid_num
) /* if doesn't have caller id */
10776 ast_log(LOG_WARNING
, "Doesnt have callerid on %s\n",tmp
);
10780 /* get his IP from IAX2 module */
10781 memset(hisip
,0,sizeof(hisip
));
10782 #ifdef ALLOW_LOCAL_CHANNELS
10783 /* set IP address if this is a local connection*/
10784 if (strncmp(chan
->name
,"Local",5)==0) {
10785 strcpy(hisip
,"127.0.0.1");
10787 pbx_substitute_variables_helper(chan
,"${IAXPEER(CURRENTCHANNEL)}",hisip
,sizeof(hisip
) - 1);
10790 pbx_substitute_variables_helper(chan
,"${IAXPEER(CURRENTCHANNEL)}",hisip
,sizeof(hisip
) - 1);
10795 ast_log(LOG_WARNING
, "Link IP address cannot be determined!!\n");
10799 ast_callerid_parse(chan
->cid
.cid_num
,&b
,&b1
);
10800 ast_shrink_phone_number(b1
);
10801 if (!strcmp(myrpt
->name
,b1
))
10803 ast_log(LOG_WARNING
, "Trying to link to self!!\n");
10809 ast_log(LOG_WARNING
, "Node %s Invalid for connection here!!\n",b1
);
10814 /* look for his reported node string */
10815 val
= node_lookup(myrpt
,b1
);
10818 ast_log(LOG_WARNING
, "Reported node %s cannot be found!!\n",b1
);
10821 strncpy(tmp
,val
,sizeof(tmp
) - 1);
10823 s1
= strsep(&s
,",");
10824 s2
= strsep(&s
,",");
10827 ast_log(LOG_WARNING
, "Reported node %s not in correct format!!\n",b1
);
10830 if (strcmp(s2
,"NONE")) {
10831 hp
= ast_gethostbyname(s2
, &ahp
);
10834 ast_log(LOG_WARNING
, "Reported node %s, name %s cannot be found!!\n",b1
,s2
);
10837 memcpy(&ia
,hp
->h_addr
,sizeof(in_addr_t
));
10838 #ifdef OLD_ASTERISK
10839 ast_inet_ntoa(nodeip
,sizeof(nodeip
) - 1,ia
);
10841 strncpy(nodeip
,ast_inet_ntoa(ia
),sizeof(nodeip
) - 1);
10843 if (strcmp(hisip
,nodeip
))
10845 char *s3
= strchr(s1
,'@');
10846 if (s3
) s1
= s3
+ 1;
10847 s3
= strchr(s1
,'/');
10849 hp
= ast_gethostbyname(s1
, &ahp
);
10852 ast_log(LOG_WARNING
, "Reported node %s, name %s cannot be found!!\n",b1
,s1
);
10855 memcpy(&ia
,hp
->h_addr
,sizeof(in_addr_t
));
10856 #ifdef OLD_ASTERISK
10857 ast_inet_ntoa(nodeip
,sizeof(nodeip
) - 1,ia
);
10859 strncpy(nodeip
,ast_inet_ntoa(ia
),sizeof(nodeip
) - 1);
10861 if (strcmp(hisip
,nodeip
))
10863 ast_log(LOG_WARNING
, "Node %s IP %s does not match link IP %s!!\n",b1
,nodeip
,hisip
);
10870 /* if is not a remote */
10871 if (!myrpt
->remote
)
10875 int reconnects
= 0;
10877 /* look at callerid to see what node this comes from */
10878 if (!chan
->cid
.cid_num
) /* if doesn't have caller id */
10880 ast_log(LOG_WARNING
, "Doesnt have callerid on %s\n",tmp
);
10884 ast_callerid_parse(chan
->cid
.cid_num
,&b
,&b1
);
10885 ast_shrink_phone_number(b1
);
10886 if (!strcmp(myrpt
->name
,b1
))
10888 ast_log(LOG_WARNING
, "Trying to link to self!!\n");
10891 rpt_mutex_lock(&myrpt
->lock
);
10892 l
= myrpt
->links
.next
;
10893 /* try to find this one in queue */
10894 while(l
!= &myrpt
->links
)
10896 if (l
->name
[0] == '0')
10901 /* if found matching string */
10902 if (!strcmp(l
->name
,b1
)) break;
10906 if (l
!= &myrpt
->links
)
10909 l
->retries
= l
->max_retries
+ 1;
10911 reconnects
= l
->reconnects
;
10913 rpt_mutex_unlock(&myrpt
->lock
);
10916 rpt_mutex_unlock(&myrpt
->lock
);
10917 /* establish call in tranceive mode */
10918 l
= malloc(sizeof(struct rpt_link
));
10921 ast_log(LOG_WARNING
, "Unable to malloc\n");
10922 pthread_exit(NULL
);
10924 /* zero the silly thing */
10925 memset((char *)l
,0,sizeof(struct rpt_link
));
10927 strncpy(l
->name
,b1
,MAXNODESTR
- 1);
10931 l
->thisconnected
= 1;
10932 l
->hasconnected
= 1;
10933 l
->reconnects
= reconnects
;
10934 l
->phonemode
= phone_mode
;
10938 ast_set_read_format(l
->chan
,AST_FORMAT_SLINEAR
);
10939 ast_set_write_format(l
->chan
,AST_FORMAT_SLINEAR
);
10940 /* allocate a pseudo-channel thru asterisk */
10941 l
->pchan
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
10944 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
10945 pthread_exit(NULL
);
10947 ast_set_read_format(l
->pchan
,AST_FORMAT_SLINEAR
);
10948 ast_set_write_format(l
->pchan
,AST_FORMAT_SLINEAR
);
10949 #ifdef AST_CDR_FLAG_POST_DISABLED
10950 ast_set_flag(l
->pchan
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
10952 /* make a conference for the tx */
10954 ci
.confno
= myrpt
->conf
;
10955 ci
.confmode
= ZT_CONF_CONF
| ZT_CONF_LISTENER
| ZT_CONF_TALKER
;
10956 /* first put the channel on the conference in proper mode */
10957 if (ioctl(l
->pchan
->fds
[0],ZT_SETCONF
,&ci
) == -1)
10959 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
10960 pthread_exit(NULL
);
10962 rpt_mutex_lock(&myrpt
->lock
);
10963 if (phone_mode
> 1) l
->lastrx
= 1;
10964 l
->max_retries
= MAX_RETRIES
;
10965 /* insert at end of queue */
10966 insque((struct qelem
*)l
,(struct qelem
*)myrpt
->links
.next
);
10967 __kickshort(myrpt
);
10968 rpt_mutex_unlock(&myrpt
->lock
);
10969 if (chan
->_state
!= AST_STATE_UP
) {
10972 if (myrpt
->p
.archivedir
)
10977 sprintf(str
,"LINK(P),%s",l
->name
);
10979 sprintf(str
,"LINK,%s",l
->name
);
10980 donodelog(myrpt
,str
);
10982 return AST_PBX_KEEPALIVE
;
10984 /* well, then it is a remote */
10985 rpt_mutex_lock(&myrpt
->lock
);
10986 /* if remote, error if anyone else already linked */
10987 if (myrpt
->remoteon
)
10989 rpt_mutex_unlock(&myrpt
->lock
);
10991 if (myrpt
->remoteon
)
10993 ast_log(LOG_WARNING
, "Trying to use busy link on %s\n",tmp
);
10996 rpt_mutex_lock(&myrpt
->lock
);
10998 if ((!strcmp(myrpt
->remote
, remote_rig_rbi
)) &&
10999 (ioperm(myrpt
->p
.iobase
,1,1) == -1))
11001 rpt_mutex_unlock(&myrpt
->lock
);
11002 ast_log(LOG_WARNING
, "Cant get io permission on IO port %x hex\n",myrpt
->p
.iobase
);
11005 myrpt
->remoteon
= 1;
11006 #ifdef OLD_ASTERISK
11009 rpt_mutex_unlock(&myrpt
->lock
);
11010 /* find our index, and load the vars initially */
11011 for(i
= 0; i
< nrpts
; i
++)
11013 if (&rpt_vars
[i
] == myrpt
)
11015 load_rpt_vars(i
,0);
11019 rpt_mutex_lock(&myrpt
->lock
);
11020 tele
= strchr(myrpt
->rxchanname
,'/');
11023 fprintf(stderr
,"rpt:Dial number must be in format tech/number\n");
11024 rpt_mutex_unlock(&myrpt
->lock
);
11025 pthread_exit(NULL
);
11028 myrpt
->rxchannel
= ast_request(myrpt
->rxchanname
,AST_FORMAT_SLINEAR
,tele
,NULL
);
11029 myrpt
->zaprxchannel
= NULL
;
11030 if (!strcasecmp(myrpt
->rxchanname
,"Zap"))
11031 myrpt
->zaprxchannel
= myrpt
->rxchannel
;
11032 if (myrpt
->rxchannel
)
11034 ast_set_read_format(myrpt
->rxchannel
,AST_FORMAT_SLINEAR
);
11035 ast_set_write_format(myrpt
->rxchannel
,AST_FORMAT_SLINEAR
);
11036 #ifdef AST_CDR_FLAG_POST_DISABLED
11037 ast_set_flag(myrpt
->rxchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
11039 myrpt
->rxchannel
->whentohangup
= 0;
11040 myrpt
->rxchannel
->appl
= "Apprpt";
11041 myrpt
->rxchannel
->data
= "(Link Rx)";
11042 if (option_verbose
> 2)
11043 ast_verbose(VERBOSE_PREFIX_3
"rpt (Rx) initiating call to %s/%s on %s\n",
11044 myrpt
->rxchanname
,tele
,myrpt
->rxchannel
->name
);
11045 rpt_mutex_unlock(&myrpt
->lock
);
11046 ast_call(myrpt
->rxchannel
,tele
,999);
11047 rpt_mutex_lock(&myrpt
->lock
);
11051 fprintf(stderr
,"rpt:Sorry unable to obtain Rx channel\n");
11052 rpt_mutex_unlock(&myrpt
->lock
);
11053 pthread_exit(NULL
);
11056 myrpt
->zaptxchannel
= NULL
;
11057 if (myrpt
->txchanname
)
11059 tele
= strchr(myrpt
->txchanname
,'/');
11062 fprintf(stderr
,"rpt:Dial number must be in format tech/number\n");
11063 rpt_mutex_unlock(&myrpt
->lock
);
11064 ast_hangup(myrpt
->rxchannel
);
11065 pthread_exit(NULL
);
11068 myrpt
->txchannel
= ast_request(myrpt
->txchanname
,AST_FORMAT_SLINEAR
,tele
,NULL
);
11069 if (!strcasecmp(myrpt
->txchanname
,"Zap"))
11070 myrpt
->zaptxchannel
= myrpt
->txchannel
;
11071 if (myrpt
->txchannel
)
11073 ast_set_read_format(myrpt
->txchannel
,AST_FORMAT_SLINEAR
);
11074 ast_set_write_format(myrpt
->txchannel
,AST_FORMAT_SLINEAR
);
11075 #ifdef AST_CDR_FLAG_POST_DISABLED
11076 ast_set_flag(myrpt
->txchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
11078 myrpt
->txchannel
->whentohangup
= 0;
11079 myrpt
->txchannel
->appl
= "Apprpt";
11080 myrpt
->txchannel
->data
= "(Link Tx)";
11081 if (option_verbose
> 2)
11082 ast_verbose(VERBOSE_PREFIX_3
"rpt (Tx) initiating call to %s/%s on %s\n",
11083 myrpt
->txchanname
,tele
,myrpt
->txchannel
->name
);
11084 rpt_mutex_unlock(&myrpt
->lock
);
11085 ast_call(myrpt
->txchannel
,tele
,999);
11086 rpt_mutex_lock(&myrpt
->lock
);
11090 fprintf(stderr
,"rpt:Sorry unable to obtain Tx channel\n");
11091 rpt_mutex_unlock(&myrpt
->lock
);
11092 ast_hangup(myrpt
->rxchannel
);
11093 pthread_exit(NULL
);
11099 myrpt
->txchannel
= myrpt
->rxchannel
;
11101 /* allocate a pseudo-channel thru asterisk */
11102 myrpt
->pchannel
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
11103 if (!myrpt
->pchannel
)
11105 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
11106 rpt_mutex_unlock(&myrpt
->lock
);
11107 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
11108 ast_hangup(myrpt
->txchannel
);
11109 ast_hangup(myrpt
->rxchannel
);
11110 pthread_exit(NULL
);
11112 ast_set_read_format(myrpt
->pchannel
,AST_FORMAT_SLINEAR
);
11113 ast_set_write_format(myrpt
->pchannel
,AST_FORMAT_SLINEAR
);
11114 #ifdef AST_CDR_FLAG_POST_DISABLED
11115 ast_set_flag(myrpt
->pchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
11117 if (!myrpt
->zaprxchannel
) myrpt
->zaprxchannel
= myrpt
->pchannel
;
11118 if (!myrpt
->zaptxchannel
) myrpt
->zaptxchannel
= myrpt
->pchannel
;
11119 /* make a conference for the pseudo */
11121 ci
.confno
= -1; /* make a new conf */
11122 ci
.confmode
= ZT_CONF_CONFANNMON
;
11123 /* first put the channel on the conference in announce/monitor mode */
11124 if (ioctl(myrpt
->pchannel
->fds
[0],ZT_SETCONF
,&ci
) == -1)
11126 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
11127 rpt_mutex_unlock(&myrpt
->lock
);
11128 ast_hangup(myrpt
->pchannel
);
11129 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
11130 ast_hangup(myrpt
->txchannel
);
11131 ast_hangup(myrpt
->rxchannel
);
11132 pthread_exit(NULL
);
11134 /* save pseudo channel conference number */
11135 myrpt
->conf
= myrpt
->txconf
= ci
.confno
;
11136 /* if serial io port, open it */
11138 if (myrpt
->p
.ioport
&& ((myrpt
->iofd
= openserial(myrpt
->p
.ioport
)) == -1))
11140 rpt_mutex_unlock(&myrpt
->lock
);
11141 ast_hangup(myrpt
->pchannel
);
11142 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
11143 ast_hangup(myrpt
->txchannel
);
11144 ast_hangup(myrpt
->rxchannel
);
11145 pthread_exit(NULL
);
11147 iskenwood_pci4
= 0;
11148 memset(&z
,0,sizeof(z
));
11149 if ((myrpt
->iofd
< 1) && (myrpt
->txchannel
== myrpt
->zaptxchannel
))
11151 z
.radpar
= ZT_RADPAR_REMMODE
;
11152 z
.data
= ZT_RADPAR_REM_NONE
;
11153 res
= ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&z
);
11154 /* if PCIRADIO and kenwood selected */
11155 if ((!res
) && (!strcmp(myrpt
->remote
,remote_rig_kenwood
)))
11157 z
.radpar
= ZT_RADPAR_UIOMODE
;
11159 if (ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&z
) == -1)
11161 ast_log(LOG_ERROR
,"Cannot set UIOMODE\n");
11164 z
.radpar
= ZT_RADPAR_UIODATA
;
11166 if (ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&z
) == -1)
11168 ast_log(LOG_ERROR
,"Cannot set UIODATA\n");
11172 if (ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_HOOK
,&i
) == -1)
11174 ast_log(LOG_ERROR
,"Cannot set hook\n");
11177 iskenwood_pci4
= 1;
11180 if (myrpt
->txchannel
== myrpt
->zaptxchannel
)
11183 ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_HOOK
,&i
);
11184 /* if PCIRADIO and Yaesu ft897/ICOM IC-706 selected */
11185 if ((myrpt
->iofd
< 1) && (!res
) &&
11186 (!strcmp(myrpt
->remote
,remote_rig_ft897
) ||
11187 (!strcmp(myrpt
->remote
,remote_rig_ic706
))))
11189 z
.radpar
= ZT_RADPAR_UIOMODE
;
11191 if (ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&z
) == -1)
11193 ast_log(LOG_ERROR
,"Cannot set UIOMODE\n");
11196 z
.radpar
= ZT_RADPAR_UIODATA
;
11198 if (ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&z
) == -1)
11200 ast_log(LOG_ERROR
,"Cannot set UIODATA\n");
11205 myrpt
->remoterx
= 0;
11206 myrpt
->remotetx
= 0;
11207 myrpt
->retxtimer
= 0;
11208 myrpt
->rerxtimer
= 0;
11209 myrpt
->remoteon
= 1;
11210 myrpt
->dtmfidx
= -1;
11211 myrpt
->dtmfbuf
[0] = 0;
11212 myrpt
->dtmf_time_rem
= 0;
11213 myrpt
->hfscanmode
= 0;
11214 myrpt
->hfscanstatus
= 0;
11215 if (myrpt
->p
.startupmacro
)
11217 snprintf(myrpt
->macrobuf
,MAXMACRO
- 1,"PPPP%s",myrpt
->p
.startupmacro
);
11219 time(&myrpt
->start_time
);
11220 myrpt
->last_activity_time
= myrpt
->start_time
;
11221 last_timeout_warning
= 0;
11223 myrpt
->tele
.next
= &myrpt
->tele
;
11224 myrpt
->tele
.prev
= &myrpt
->tele
;
11225 rpt_mutex_unlock(&myrpt
->lock
);
11226 ast_set_write_format(chan
, AST_FORMAT_SLINEAR
);
11227 ast_set_read_format(chan
, AST_FORMAT_SLINEAR
);
11230 /* if we are on 2w loop and are a remote, turn EC on */
11231 if (myrpt
->remote
&& (myrpt
->rxchannel
== myrpt
->txchannel
))
11234 ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_ECHOCANCEL
,&i
);
11236 if (chan
->_state
!= AST_STATE_UP
) {
11240 if (myrpt
->rxchannel
== myrpt
->zaprxchannel
)
11242 if (ioctl(myrpt
->zaprxchannel
->fds
[0],ZT_GET_PARAMS
,&par
) != -1)
11244 if (par
.rxisoffhook
)
11246 ast_indicate(chan
,AST_CONTROL_RADIO_KEY
);
11247 myrpt
->remoterx
= 1;
11252 if (myrpt
->p
.archivedir
)
11254 char mycmd
[100],mydate
[100],*b
,*b1
;
11259 mkdir(myrpt
->p
.archivedir
,0600);
11260 sprintf(mycmd
,"%s/%s",myrpt
->p
.archivedir
,myrpt
->name
);
11263 strftime(mydate
,sizeof(mydate
) - 1,"%Y%m%d%H%M%S",
11265 sprintf(mycmd
,"mixmonitor start %s %s/%s/%s.wav49 a",chan
->name
,
11266 myrpt
->p
.archivedir
,myrpt
->name
,mydate
);
11267 if (myrpt
->p
.monminblocks
)
11269 blocksleft
= diskavail(myrpt
);
11270 if (myrpt
->p
.remotetimeout
)
11272 blocksleft
-= (myrpt
->p
.remotetimeout
*
11273 MONITOR_DISK_BLOCKS_PER_MINUTE
) / 60;
11275 if (blocksleft
>= myrpt
->p
.monminblocks
)
11276 ast_cli_command(nullfd
,mycmd
);
11277 } else ast_cli_command(nullfd
,mycmd
);
11278 /* look at callerid to see what node this comes from */
11279 if (!chan
->cid
.cid_num
) /* if doesn't have caller id */
11283 ast_callerid_parse(chan
->cid
.cid_num
,&b
,&b1
);
11284 ast_shrink_phone_number(b1
);
11286 sprintf(mycmd
,"CONNECT,%s",b1
);
11287 donodelog(myrpt
,mycmd
);
11289 myrpt
->loginuser
[0] = 0;
11290 myrpt
->loginlevel
[0] = 0;
11291 myrpt
->authtelltimer
= 0;
11292 myrpt
->authtimer
= 0;
11295 if (myrpt
->p
.authlevel
> 1) authreq
= 1;
11300 cs
[n
++] = myrpt
->rxchannel
;
11301 cs
[n
++] = myrpt
->pchannel
;
11302 if (myrpt
->rxchannel
!= myrpt
->txchannel
)
11303 cs
[n
++] = myrpt
->txchannel
;
11304 /* start un-locked */
11307 if (ast_check_hangup(chan
)) break;
11308 if (ast_check_hangup(myrpt
->rxchannel
)) break;
11312 telem
= myrpt
->tele
.next
;
11313 while(telem
!= &myrpt
->tele
)
11315 if (telem
->mode
== SETREMOTE
) setting
= 1;
11316 if ((telem
->mode
== SETREMOTE
) ||
11317 (telem
->mode
== SCAN
) ||
11318 (telem
->mode
== TUNE
)) reming
= 1;
11319 else notremming
= 1;
11320 telem
= telem
->next
;
11325 /* find our index, and load the vars */
11326 for(i
= 0; i
< nrpts
; i
++)
11328 if (&rpt_vars
[i
] == myrpt
)
11330 load_rpt_vars(i
,0);
11336 if (myrpt
->p
.remotetimeout
)
11340 r
= (t
- myrpt
->start_time
);
11341 if (r
>= myrpt
->p
.remotetimeout
)
11343 sayfile(chan
,"rpt/node");
11344 ast_say_character_str(chan
,myrpt
->name
,NULL
,chan
->language
);
11345 sayfile(chan
,"rpt/timeout");
11346 ast_safe_sleep(chan
,1000);
11349 if ((myrpt
->p
.remotetimeoutwarning
) &&
11350 (r
>= (myrpt
->p
.remotetimeout
-
11351 myrpt
->p
.remotetimeoutwarning
)) &&
11352 (r
<= (myrpt
->p
.remotetimeout
-
11353 myrpt
->p
.remotetimeoutwarningfreq
)))
11355 if (myrpt
->p
.remotetimeoutwarningfreq
)
11357 if ((t
- last_timeout_warning
) >=
11358 myrpt
->p
.remotetimeoutwarningfreq
)
11360 time(&last_timeout_warning
);
11361 rpt_telemetry(myrpt
,TIMEOUT_WARNING
,0);
11366 if (!last_timeout_warning
)
11368 time(&last_timeout_warning
);
11369 rpt_telemetry(myrpt
,TIMEOUT_WARNING
,0);
11374 if (myrpt
->p
.remoteinacttimeout
&& myrpt
->last_activity_time
)
11378 r
= (t
- myrpt
->last_activity_time
);
11379 if (r
>= myrpt
->p
.remoteinacttimeout
)
11381 sayfile(chan
,"rpt/node");
11382 ast_say_character_str(chan
,myrpt
->name
,NULL
,chan
->language
);
11383 sayfile(chan
,"rpt/timeout");
11384 ast_safe_sleep(chan
,1000);
11387 if ((myrpt
->p
.remotetimeoutwarning
) &&
11388 (r
>= (myrpt
->p
.remoteinacttimeout
-
11389 myrpt
->p
.remotetimeoutwarning
)) &&
11390 (r
<= (myrpt
->p
.remoteinacttimeout
-
11391 myrpt
->p
.remotetimeoutwarningfreq
)))
11393 if (myrpt
->p
.remotetimeoutwarningfreq
)
11395 if ((t
- last_timeout_warning
) >=
11396 myrpt
->p
.remotetimeoutwarningfreq
)
11398 time(&last_timeout_warning
);
11399 rpt_telemetry(myrpt
,ACT_TIMEOUT_WARNING
,0);
11404 if (!last_timeout_warning
)
11406 time(&last_timeout_warning
);
11407 rpt_telemetry(myrpt
,ACT_TIMEOUT_WARNING
,0);
11413 who
= ast_waitfor_n(cs
,n
,&ms
);
11414 if (who
== NULL
) ms
= 0;
11415 elap
= MSWAIT
- ms
;
11416 if (myrpt
->macrotimer
) myrpt
->macrotimer
-= elap
;
11417 if (myrpt
->macrotimer
< 0) myrpt
->macrotimer
= 0;
11419 /* do local dtmf timer */
11420 if (myrpt
->dtmf_local_timer
)
11422 if (myrpt
->dtmf_local_timer
> 1) myrpt
->dtmf_local_timer
-= elap
;
11423 if (myrpt
->dtmf_local_timer
< 1) myrpt
->dtmf_local_timer
= 1;
11425 rpt_mutex_lock(&myrpt
->lock
);
11426 do_dtmf_local(myrpt
,0);
11427 rpt_mutex_unlock(&myrpt
->lock
);
11428 rem_totx
= myrpt
->dtmf_local_timer
&& (!phone_mode
);
11429 rem_totx
|= keyed
&& (!myrpt
->tunerequest
);
11430 rem_rx
= (remkeyed
&& (!setting
)) || (myrpt
->tele
.next
!= &myrpt
->tele
);
11431 if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
11432 rem_totx
|= myrpt
->tunerequest
;
11433 if (keyed
&& (!keyed1
))
11438 if (!keyed
&& (keyed1
))
11444 /* if login necessary, and not too soon */
11445 if ((myrpt
->p
.authlevel
) &&
11446 (!myrpt
->loginlevel
[0]) &&
11451 myrpt
->authtelltimer
= AUTHTELLTIME
- AUTHTXTIME
;
11456 if (rem_rx
&& (!myrpt
->remoterx
))
11458 myrpt
->remoterx
= 1;
11459 ast_indicate(chan
,AST_CONTROL_RADIO_KEY
);
11461 if ((!rem_rx
) && (myrpt
->remoterx
))
11463 myrpt
->remoterx
= 0;
11464 ast_indicate(chan
,AST_CONTROL_RADIO_UNKEY
);
11466 /* if auth requested, and not authed yet */
11467 if (authreq
&& (!myrpt
->loginlevel
[0]))
11469 if ((!authtold
) && ((myrpt
->authtelltimer
+= elap
)
11473 rpt_telemetry(myrpt
,LOGINREQ
,NULL
);
11475 if ((myrpt
->authtimer
+= elap
) >= AUTHLOGOUTTIME
)
11477 break; /* if not logged in, hang up after a time */
11481 if ((myrpt
->retxtimer
+= elap
) >= REDUNDANT_TX_TIME
)
11483 myrpt
->retxtimer
= 0;
11484 if ((myrpt
->remoterx
) && (!myrpt
->remotetx
))
11485 ast_indicate(chan
,AST_CONTROL_RADIO_KEY
);
11487 ast_indicate(chan
,AST_CONTROL_RADIO_UNKEY
);
11490 if ((myrpt
->rerxtimer
+= elap
) >= (REDUNDANT_TX_TIME
* 2))
11493 myrpt
->rerxtimer
= 0;
11496 if (rem_totx
&& (!myrpt
->remotetx
))
11498 /* if not authed, and needed, dont transmit */
11499 if ((!myrpt
->p
.authlevel
) || myrpt
->loginlevel
[0])
11501 myrpt
->remotetx
= 1;
11502 if((myrpt
->remtxfreqok
= check_tx_freq(myrpt
)))
11504 time(&myrpt
->last_activity_time
);
11505 if ((iskenwood_pci4
) && (myrpt
->txchannel
== myrpt
->zaptxchannel
))
11507 z
.radpar
= ZT_RADPAR_UIODATA
;
11509 if (ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&z
) == -1)
11511 ast_log(LOG_ERROR
,"Cannot set UIODATA\n");
11517 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_KEY
);
11519 if (myrpt
->p
.archivedir
) donodelog(myrpt
,"TXKEY");
11523 if ((!rem_totx
) && myrpt
->remotetx
) /* Remote base radio TX unkey */
11525 myrpt
->remotetx
= 0;
11526 if(!myrpt
->remtxfreqok
){
11527 rpt_telemetry(myrpt
,UNAUTHTX
,NULL
);
11529 if ((iskenwood_pci4
) && (myrpt
->txchannel
== myrpt
->zaptxchannel
))
11531 z
.radpar
= ZT_RADPAR_UIODATA
;
11533 if (ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&z
) == -1)
11535 ast_log(LOG_ERROR
,"Cannot set UIODATA\n");
11541 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_UNKEY
);
11543 if (myrpt
->p
.archivedir
) donodelog(myrpt
,"TXUNKEY");
11545 if (myrpt
->hfscanmode
){
11546 myrpt
->scantimer
-= elap
;
11547 if(myrpt
->scantimer
<= 0){
11550 myrpt
->scantimer
= REM_SCANTIME
;
11551 rpt_telemetry(myrpt
,SCAN
,0);
11552 } else myrpt
->scantimer
= 1;
11555 rpt_mutex_lock(&myrpt
->lock
);
11556 c
= myrpt
->macrobuf
[0];
11557 if (c
&& (!myrpt
->macrotimer
))
11559 myrpt
->macrotimer
= MACROTIME
;
11560 memmove(myrpt
->macrobuf
,myrpt
->macrobuf
+ 1,MAXMACRO
- 1);
11561 if ((c
== 'p') || (c
== 'P'))
11562 myrpt
->macrotimer
= MACROPTIME
;
11563 rpt_mutex_unlock(&myrpt
->lock
);
11564 if (myrpt
->p
.archivedir
)
11567 sprintf(str
,"DTMF(M),%c",c
);
11568 donodelog(myrpt
,str
);
11570 if (handle_remote_dtmf_digit(myrpt
,c
,&keyed
,0) == -1) break;
11572 } else rpt_mutex_unlock(&myrpt
->lock
);
11573 if (who
== chan
) /* if it was a read from incomming */
11575 f
= ast_read(chan
);
11578 if (debug
) printf("@@@@ link:Hung Up\n");
11581 if (f
->frametype
== AST_FRAME_VOICE
)
11583 if (ioctl(chan
->fds
[0], ZT_GETCONFMUTE
, &ismuted
) == -1)
11587 /* if not transmitting, zero-out audio */
11588 ismuted
|= (!myrpt
->remotetx
);
11589 if (dtmfed
&& phone_mode
) ismuted
= 1;
11593 memset(f
->data
,0,f
->datalen
);
11595 memset(myrpt
->lastf1
->data
,0,myrpt
->lastf1
->datalen
);
11597 memset(myrpt
->lastf2
->data
,0,myrpt
->lastf2
->datalen
);
11599 if (f
) f2
= ast_frdup(f
);
11601 f1
= myrpt
->lastf2
;
11602 myrpt
->lastf2
= myrpt
->lastf1
;
11603 myrpt
->lastf1
= f2
;
11607 memset(myrpt
->lastf1
->data
,0,myrpt
->lastf1
->datalen
);
11609 memset(myrpt
->lastf2
->data
,0,myrpt
->lastf2
->datalen
);
11614 ast_write(myrpt
->txchannel
,f1
);
11616 ast_write(myrpt
->txchannel
,f
);
11620 #ifndef OLD_ASTERISK
11621 else if (f
->frametype
== AST_FRAME_DTMF_BEGIN
)
11624 memset(myrpt
->lastf1
->data
,0,myrpt
->lastf1
->datalen
);
11626 memset(myrpt
->lastf2
->data
,0,myrpt
->lastf2
->datalen
);
11630 if (f
->frametype
== AST_FRAME_DTMF
)
11633 memset(myrpt
->lastf1
->data
,0,myrpt
->lastf1
->datalen
);
11635 memset(myrpt
->lastf2
->data
,0,myrpt
->lastf2
->datalen
);
11637 if (handle_remote_phone_dtmf(myrpt
,f
->subclass
,&keyed
,phone_mode
) == -1)
11639 if (debug
) printf("@@@@ rpt:Hung Up\n");
11644 if (f
->frametype
== AST_FRAME_TEXT
)
11646 if (handle_remote_data(myrpt
,f
->data
) == -1)
11648 if (debug
) printf("@@@@ rpt:Hung Up\n");
11653 if (f
->frametype
== AST_FRAME_CONTROL
)
11655 if (f
->subclass
== AST_CONTROL_HANGUP
)
11657 if (debug
) printf("@@@@ rpt:Hung Up\n");
11662 if (f
->subclass
== AST_CONTROL_RADIO_KEY
)
11664 if (debug
== 7) printf("@@@@ rx key\n");
11666 myrpt
->rerxtimer
= 0;
11669 if (f
->subclass
== AST_CONTROL_RADIO_UNKEY
)
11671 myrpt
->rerxtimer
= 0;
11672 if (debug
== 7) printf("@@@@ rx un-key\n");
11679 if (who
== myrpt
->rxchannel
) /* if it was a read from radio */
11681 f
= ast_read(myrpt
->rxchannel
);
11684 if (debug
) printf("@@@@ link:Hung Up\n");
11687 if (f
->frametype
== AST_FRAME_VOICE
)
11691 if(!strcmp(myrpt
->remote
, remote_rig_kenwood
))
11694 if (myreming
|| (!remkeyed
) ||
11695 ((myrpt
->remote
) && (myrpt
->remotetx
)) ||
11696 ((myrpt
->remmode
!= REM_MODE_FM
) &&
11698 memset(f
->data
,0,f
->datalen
);
11699 ast_write(myrpt
->pchannel
,f
);
11701 else if (f
->frametype
== AST_FRAME_CONTROL
)
11703 if (f
->subclass
== AST_CONTROL_HANGUP
)
11705 if (debug
) printf("@@@@ rpt:Hung Up\n");
11710 if (f
->subclass
== AST_CONTROL_RADIO_KEY
)
11712 if (debug
== 7) printf("@@@@ remote rx key\n");
11713 if (!myrpt
->remotetx
)
11719 if (f
->subclass
== AST_CONTROL_RADIO_UNKEY
)
11721 if (debug
== 7) printf("@@@@ remote rx un-key\n");
11722 if (!myrpt
->remotetx
)
11731 if (who
== myrpt
->pchannel
) /* if is remote mix output */
11733 f
= ast_read(myrpt
->pchannel
);
11736 if (debug
) printf("@@@@ link:Hung Up\n");
11739 if (f
->frametype
== AST_FRAME_VOICE
)
11743 if (f
->frametype
== AST_FRAME_CONTROL
)
11745 if (f
->subclass
== AST_CONTROL_HANGUP
)
11747 if (debug
) printf("@@@@ rpt:Hung Up\n");
11755 if ((myrpt
->rxchannel
!= myrpt
->txchannel
) &&
11756 (who
== myrpt
->txchannel
)) /* do this cuz you have to */
11758 f
= ast_read(myrpt
->txchannel
);
11761 if (debug
) printf("@@@@ link:Hung Up\n");
11764 if (f
->frametype
== AST_FRAME_CONTROL
)
11766 if (f
->subclass
== AST_CONTROL_HANGUP
)
11768 if (debug
) printf("@@@@ rpt:Hung Up\n");
11777 if (myrpt
->p
.archivedir
)
11779 char mycmd
[100],*b
,*b1
;
11781 /* look at callerid to see what node this comes from */
11782 if (!chan
->cid
.cid_num
) /* if doesn't have caller id */
11786 ast_callerid_parse(chan
->cid
.cid_num
,&b
,&b1
);
11787 ast_shrink_phone_number(b1
);
11789 sprintf(mycmd
,"DISCONNECT,%s",b1
);
11790 donodelog(myrpt
,mycmd
);
11792 /* wait for telem to be done */
11793 while(myrpt
->tele
.next
!= &myrpt
->tele
) usleep(100000);
11794 sprintf(tmp
,"mixmonitor stop %s",chan
->name
);
11795 ast_cli_command(nullfd
,tmp
);
11797 rpt_mutex_lock(&myrpt
->lock
);
11798 myrpt
->hfscanmode
= 0;
11799 myrpt
->hfscanstatus
= 0;
11800 myrpt
->remoteon
= 0;
11801 rpt_mutex_unlock(&myrpt
->lock
);
11802 if (myrpt
->lastf1
) ast_frfree(myrpt
->lastf1
);
11803 myrpt
->lastf1
= NULL
;
11804 if (myrpt
->lastf2
) ast_frfree(myrpt
->lastf2
);
11805 myrpt
->lastf2
= NULL
;
11806 if ((iskenwood_pci4
) && (myrpt
->txchannel
== myrpt
->zaptxchannel
))
11808 z
.radpar
= ZT_RADPAR_UIOMODE
;
11810 if (ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&z
) == -1)
11812 ast_log(LOG_ERROR
,"Cannot set UIOMODE\n");
11815 z
.radpar
= ZT_RADPAR_UIODATA
;
11817 if (ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_RADIO_SETPARAM
,&z
) == -1)
11819 ast_log(LOG_ERROR
,"Cannot set UIODATA\n");
11823 if (ioctl(myrpt
->zaptxchannel
->fds
[0],ZT_HOOK
,&i
) == -1)
11825 ast_log(LOG_ERROR
,"Cannot set hook\n");
11829 if (myrpt
->iofd
) close(myrpt
->iofd
);
11831 ast_hangup(myrpt
->pchannel
);
11832 if (myrpt
->rxchannel
!= myrpt
->txchannel
) ast_hangup(myrpt
->txchannel
);
11833 ast_hangup(myrpt
->rxchannel
);
11835 #ifdef OLD_ASTERISK
11836 LOCAL_USER_REMOVE(u
);
11841 #ifdef OLD_ASTERISK
11842 int unload_module()
11844 static int unload_module(void)
11849 #ifdef OLD_ASTERISK
11850 STANDARD_HANGUP_LOCALUSERS
;
11852 for(i
= 0; i
< nrpts
; i
++) {
11853 if (!strcmp(rpt_vars
[i
].name
,rpt_vars
[i
].p
.nodes
)) continue;
11854 ast_mutex_destroy(&rpt_vars
[i
].lock
);
11855 ast_mutex_destroy(&rpt_vars
[i
].remlock
);
11857 i
= ast_unregister_application(app
);
11859 /* Unregister cli extensions */
11860 ast_cli_unregister(&cli_debug
);
11861 ast_cli_unregister(&cli_dump
);
11862 ast_cli_unregister(&cli_stats
);
11863 ast_cli_unregister(&cli_lstats
);
11864 ast_cli_unregister(&cli_nodes
);
11865 ast_cli_unregister(&cli_reload
);
11866 ast_cli_unregister(&cli_restart
);
11867 ast_cli_unregister(&cli_fun
);
11872 #ifdef OLD_ASTERISK
11875 static int load_module(void)
11878 ast_pthread_create(&rpt_master_thread
,NULL
,rpt_master
,NULL
);
11880 /* Register cli extensions */
11881 ast_cli_register(&cli_debug
);
11882 ast_cli_register(&cli_dump
);
11883 ast_cli_register(&cli_stats
);
11884 ast_cli_register(&cli_lstats
);
11885 ast_cli_register(&cli_nodes
);
11886 ast_cli_register(&cli_reload
);
11887 ast_cli_register(&cli_restart
);
11888 ast_cli_register(&cli_fun
);
11890 return ast_register_application(app
, rpt_exec
, synopsis
, descrip
);
11893 #ifdef OLD_ASTERISK
11894 char *description()
11901 STANDARD_USECOUNT(res
);
11907 return ASTERISK_GPL_KEY
;
11911 #ifdef OLD_ASTERISK
11914 static int reload(void)
11919 for(n
= 0; n
< nrpts
; n
++) rpt_vars
[n
].reload
= 1;
11923 #ifndef OLD_ASTERISK
11924 /* STD_MOD(MOD_1, reload, NULL, NULL); */
11925 AST_MODULE_INFO(ASTERISK_GPL_KEY
, AST_MODFLAG_DEFAULT
, "Radio Repeater/Remote Base Application",
11926 .load
= load_module
,
11927 .unload
= unload_module
,