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>dahdi</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>
279 #include <netinet/in.h>
280 #include <arpa/inet.h>
283 #include "asterisk/utils.h"
284 #include "asterisk/lock.h"
285 #include "asterisk/file.h"
286 #include "asterisk/logger.h"
287 #include "asterisk/channel.h"
288 #include "asterisk/callerid.h"
289 #include "asterisk/pbx.h"
290 #include "asterisk/module.h"
291 #include "asterisk/translate.h"
292 #include "asterisk/features.h"
293 #include "asterisk/options.h"
294 #include "asterisk/cli.h"
295 #include "asterisk/config.h"
296 #include "asterisk/say.h"
297 #include "asterisk/localtime.h"
298 #include "asterisk/cdr.h"
299 #include "asterisk/options.h"
301 #include "asterisk/dahdi_compat.h"
302 #include "asterisk/tonezone_compat.h"
304 /* Start a tone-list going */
305 int ast_playtones_start(struct ast_channel
*chan
, int vol
, const char* tonelist
, int interruptible
);
306 /*! Stop the tones from playing */
307 void ast_playtones_stop(struct ast_channel
*chan
);
309 static char *tdesc
= "Radio Repeater / Remote Base version 0.73 09/04/2007";
311 static char *app
= "Rpt";
313 static char *synopsis
= "Radio Repeater/Remote Base Control System";
315 static char *descrip
=
316 " Rpt(nodename[|options]): Radio Remote Link or Remote Base Link Endpoint Process.\n"
318 " Not specifying an option puts it in normal endpoint mode (where source\n"
319 " IP and nodename are verified).\n"
321 " Options are as follows:\n"
323 " X - Normal endpoint mode WITHOUT security check. Only specify\n"
324 " this if you have checked security already (like with an IAX2\n"
325 " user/password or something).\n"
327 " Rannounce-string[|timeout[|timeout-destination]] - Amateur Radio\n"
328 " Reverse Autopatch. Caller is put on hold, and announcement (as\n"
329 " specified by the 'announce-string') is played on radio system.\n"
330 " Users of radio system can access autopatch, dial specified\n"
331 " code, and pick up call. Announce-string is list of names of\n"
332 " recordings, or \"PARKED\" to substitute code for un-parking,\n"
333 " or \"NODE\" to substitute node number.\n"
335 " P - Phone Control mode. This allows a regular phone user to have\n"
336 " full control and audio access to the radio system. For the\n"
337 " user to have DTMF control, the 'phone_functions' parameter\n"
338 " must be specified for the node in 'rpt.conf'. An additional\n"
339 " function (cop,6) must be listed so that PTT control is available.\n"
341 " D - Dumb Phone Control mode. This allows a regular phone user to\n"
342 " have full control and audio access to the radio system. In this\n"
343 " mode, the PTT is activated for the entire length of the call.\n"
344 " For the user to have DTMF control (not generally recomended in\n"
345 " this mode), the 'dphone_functions' parameter must be specified\n"
346 " for the node in 'rpt.conf'. Otherwise no DTMF control will be\n"
347 " available to the phone user.\n"
350 static int debug
= 0; /* Set this >0 for extra debug output */
351 static int nrpts
= 0;
353 static char remdtmfstr
[] = "0123456789*#ABCD";
355 enum {TOP_TOP
,TOP_WON
,WON_BEFREAD
,BEFREAD_AFTERREAD
};
357 int max_chan_stat
[] = {22000,1000,22000,100,22000,2000,22000};
366 unsigned long largest
;
367 struct timeval largest_time
;
370 char *discstr
= "!!DISCONNECT!!";
371 static char *remote_rig_ft897
="ft897";
372 static char *remote_rig_rbi
="rbi";
373 static char *remote_rig_kenwood
="kenwood";
374 static char *remote_rig_ic706
="ic706";
382 #define HANGTIME 5000
383 #define TOTIME 180000
384 #define IDTIME 300000
386 #define MAX_STAT_LINKS 32
387 #define POLITEID 30000
388 #define FUNCTDELAY 1500
391 #define MAXXLATTIME 3
393 #define MAX_SYSSTATES 10
397 char funccharseq
[MAXXLAT
];
398 char endcharseq
[MAXXLAT
];
399 char passchars
[MAXXLAT
];
405 static time_t starttime
= 0;
407 static pthread_t rpt_master_thread
;
413 struct rpt_link
*next
;
414 struct rpt_link
*prev
;
415 char mode
; /* 1 if in tx mode */
418 char name
[MAXNODESTR
]; /* identifier (routing) string */
437 long long connecttime
;
438 struct ast_channel
*chan
;
439 struct ast_channel
*pchan
;
440 char linklist
[MAXLINKLIST
];
441 time_t linklistreceived
;
444 int linkunkeytocttimer
;
445 struct ast_frame
*lastf1
,*lastf2
;
446 struct rpt_chan_stat chan_stat
[NRPTSTAT
];
451 struct rpt_lstat
*next
;
452 struct rpt_lstat
*prev
;
453 char peer
[MAXPEERSTR
];
454 char name
[MAXNODESTR
];
459 long long connecttime
;
460 struct rpt_chan_stat chan_stat
[NRPTSTAT
];
465 struct rpt_tele
*next
;
466 struct rpt_tele
*prev
;
468 struct ast_channel
*chan
;
470 struct rpt_link mylink
;
471 char param
[TELEPARAMSIZE
];
476 struct function_table_tag
478 char action
[ACTIONSIZE
];
479 int (*function
)(struct rpt
*myrpt
, char *param
, char *digitbuf
,
480 int command_source
, struct rpt_link
*mylink
);
483 /* Used to store the morse code patterns */
491 struct telem_defaults
503 char autopatchdisable
;
504 char schedulerdisable
;
513 struct ast_config
*cfg
;
520 struct rpt_chan_stat chan_stat
[NRPTSTAT
];
531 char *link_functions
;
532 char *phone_functions
;
533 char *dphone_functions
;
542 int tailsquashedtime
;
545 char *tailmessages
[500];
557 char propagate_phonedtmf
;
559 unsigned char civaddr
;
560 struct rpt_xlat inxlat
;
561 struct rpt_xlat outxlat
;
565 char *skedstanzaname
;
566 char *txlimitsstanzaname
;
568 int remoteinacttimeout
;
570 int remotetimeoutwarning
;
571 int remotetimeoutwarningfreq
;
573 struct sysstate s
[MAX_SYSSTATES
];
575 struct rpt_link links
;
586 char dtmfbuf
[MAXDTMF
];
587 char macrobuf
[MAXMACRO
];
588 char rem_dtmfbuf
[MAXDTMF
];
589 char lastdtmfcommand
[MAXDTMF
];
591 struct ast_channel
*rxchannel
,*txchannel
, *monchannel
;
592 struct ast_channel
*pchannel
,*txpchannel
, *zaprxchannel
, *zaptxchannel
;
593 struct ast_frame
*lastf1
,*lastf2
;
594 struct rpt_tele tele
;
595 struct timeval lasttv
,curtv
;
596 pthread_t rpt_call_thread
,rpt_thread
;
597 time_t dtmf_time
,rem_dtmf_time
,dtmf_time_rem
;
598 int tailtimer
,totimer
,idtimer
,txconf
,conf
,callmode
,cidx
,scantimer
,tmsgtimer
,skedtimer
;
602 int dtmfidx
,rem_dtmfidx
;
603 int dailytxtime
,dailykerchunks
,totalkerchunks
,dailykeyups
,totalkeyups
,timeouts
;
604 int totalexecdcommands
, dailyexecdcommands
;
607 long long totaltxtime
;
609 char exten
[AST_MAX_EXTENSION
];
610 char freq
[MAXREMSTR
],rxpl
[MAXREMSTR
],txpl
[MAXREMSTR
];
620 char lastlinknode
[MAXNODESTR
];
621 char savednodes
[MAXNODESTR
];
623 char patchfarenddisconnect
;
626 char patchcontext
[MAXPATCHCONTEXT
];
629 int phone_longestfunc
;
630 int dphone_longestfunc
;
631 int link_longestfunc
;
637 time_t lastthreadrestarttime
;
639 char lastnodewhichkeyedusup
[MAXNODESTR
];
640 int dtmf_local_timer
;
641 char dtmf_local_str
[100];
642 struct ast_filestream
*monstream
;
648 time_t start_time
,last_activity_time
;
663 } filters
[MAXFILTERS
];
665 #ifdef _MDC_DECODE_H_
667 unsigned short lastunit
;
672 struct nodelog
*next
;
673 struct nodelog
*prev
;
675 char archivedir
[MAXNODESTR
];
676 char str
[MAXNODESTR
* 2];
679 static int service_scan(struct rpt
*myrpt
);
680 static int set_mode_ft897(struct rpt
*myrpt
, char newmode
);
681 static int set_mode_ic706(struct rpt
*myrpt
, char newmode
);
682 static int simple_command_ft897(struct rpt
*myrpt
, char command
);
683 static int setrem(struct rpt
*myrpt
);
685 AST_MUTEX_DEFINE_STATIC(nodeloglock
);
687 AST_MUTEX_DEFINE_STATIC(nodelookuplock
);
689 #ifdef APP_RPT_LOCK_DEBUG
691 #warning COMPILING WITH LOCK-DEBUGGING ENABLED!!
693 #define MAXLOCKTHREAD 100
695 #define rpt_mutex_lock(x) _rpt_mutex_lock(x,myrpt,__LINE__)
696 #define rpt_mutex_unlock(x) _rpt_mutex_unlock(x,myrpt,__LINE__)
704 } lockthreads
[MAXLOCKTHREAD
];
712 struct lockthread lockthread
;
715 int lock_ring_index
= 0;
717 AST_MUTEX_DEFINE_STATIC(locklock
);
719 static struct lockthread
*get_lockthread(pthread_t id
)
723 for(i
= 0; i
< MAXLOCKTHREAD
; i
++)
725 if (lockthreads
[i
].id
== id
) return(&lockthreads
[i
]);
730 static struct lockthread
*put_lockthread(pthread_t id
)
734 for(i
= 0; i
< MAXLOCKTHREAD
; i
++)
736 if (lockthreads
[i
].id
== id
)
737 return(&lockthreads
[i
]);
739 for(i
= 0; i
< MAXLOCKTHREAD
; i
++)
741 if (!lockthreads
[i
].id
)
743 lockthreads
[i
].lockcount
= 0;
744 lockthreads
[i
].lastlock
= 0;
745 lockthreads
[i
].lastunlock
= 0;
746 lockthreads
[i
].id
= id
;
747 return(&lockthreads
[i
]);
754 static void rpt_mutex_spew(void)
756 struct by_lightning lock_ring_copy
[32];
757 int lock_ring_index_copy
;
761 struct timeval lasttv
;
763 ast_mutex_lock(&locklock
);
764 memcpy(&lock_ring_copy
, &lock_ring
, sizeof(lock_ring_copy
));
765 lock_ring_index_copy
= lock_ring_index
;
766 ast_mutex_unlock(&locklock
);
768 lasttv
.tv_sec
= lasttv
.tv_usec
= 0;
769 for(i
= 0 ; i
< 32 ; i
++)
771 j
= (i
+ lock_ring_index_copy
) % 32;
772 strftime(a
,sizeof(a
) - 1,"%m/%d/%Y %H:%M:%S",
773 localtime(&lock_ring_copy
[j
].tv
.tv_sec
));
777 diff
= (lock_ring_copy
[j
].tv
.tv_sec
- lasttv
.tv_sec
)
779 diff
+= (lock_ring_copy
[j
].tv
.tv_usec
- lasttv
.tv_usec
);
781 lasttv
.tv_sec
= lock_ring_copy
[j
].tv
.tv_sec
;
782 lasttv
.tv_usec
= lock_ring_copy
[j
].tv
.tv_usec
;
783 if (!lock_ring_copy
[j
].tv
.tv_sec
) continue;
784 if (lock_ring_copy
[j
].line
< 0)
786 ast_log(LOG_NOTICE
,"LOCKDEBUG [#%d] UNLOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
787 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
);
791 ast_log(LOG_NOTICE
,"LOCKDEBUG [#%d] LOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
792 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
);
798 static void _rpt_mutex_lock(ast_mutex_t
*lockp
, struct rpt
*myrpt
, int line
)
800 struct lockthread
*t
;
804 ast_mutex_lock(&locklock
);
805 t
= put_lockthread(id
);
808 ast_mutex_unlock(&locklock
);
813 int lastline
= t
->lastlock
;
814 ast_mutex_unlock(&locklock
);
815 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
);
821 gettimeofday(&lock_ring
[lock_ring_index
].tv
, NULL
);
822 lock_ring
[lock_ring_index
].rpt
= myrpt
;
823 memcpy(&lock_ring
[lock_ring_index
].lockthread
,t
,sizeof(struct lockthread
));
824 lock_ring
[lock_ring_index
++].line
= line
;
825 if(lock_ring_index
== 32)
827 ast_mutex_unlock(&locklock
);
828 ast_mutex_lock(lockp
);
832 static void _rpt_mutex_unlock(ast_mutex_t
*lockp
, struct rpt
*myrpt
, int line
)
834 struct lockthread
*t
;
838 ast_mutex_lock(&locklock
);
839 t
= put_lockthread(id
);
842 ast_mutex_unlock(&locklock
);
847 int lastline
= t
->lastunlock
;
848 ast_mutex_unlock(&locklock
);
849 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
);
853 t
->lastunlock
= line
;
855 gettimeofday(&lock_ring
[lock_ring_index
].tv
, NULL
);
856 lock_ring
[lock_ring_index
].rpt
= myrpt
;
857 memcpy(&lock_ring
[lock_ring_index
].lockthread
,t
,sizeof(struct lockthread
));
858 lock_ring
[lock_ring_index
++].line
= -line
;
859 if(lock_ring_index
== 32)
861 ast_mutex_unlock(&locklock
);
862 ast_mutex_unlock(lockp
);
865 #else /* APP_RPT_LOCK_DEBUG */
867 #define rpt_mutex_lock(x) ast_mutex_lock(x)
868 #define rpt_mutex_unlock(x) ast_mutex_unlock(x)
870 #endif /* APP_RPT_LOCK_DEBUG */
873 * Return 1 if rig is multimode capable
876 static int multimode_capable(struct rpt
*myrpt
)
878 if(!strcmp(myrpt
->remote
, remote_rig_ft897
))
880 if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
890 static int rpt_do_debug(int fd
, int argc
, char *argv
[]);
891 static int rpt_do_dump(int fd
, int argc
, char *argv
[]);
892 static int rpt_do_stats(int fd
, int argc
, char *argv
[]);
893 static int rpt_do_lstats(int fd
, int argc
, char *argv
[]);
894 static int rpt_do_nodes(int fd
, int argc
, char *argv
[]);
895 static int rpt_do_reload(int fd
, int argc
, char *argv
[]);
896 static int rpt_do_restart(int fd
, int argc
, char *argv
[]);
897 static int rpt_do_fun(int fd
, int argc
, char *argv
[]);
899 static char debug_usage
[] =
900 "Usage: rpt debug level {0-7}\n"
901 " Enables debug messages in app_rpt\n";
903 static char dump_usage
[] =
904 "Usage: rpt dump <nodename>\n"
905 " Dumps struct debug info to log\n";
907 static char dump_stats
[] =
908 "Usage: rpt stats <nodename>\n"
909 " Dumps node statistics to console\n";
911 static char dump_lstats
[] =
912 "Usage: rpt lstats <nodename>\n"
913 " Dumps link statistics to console\n";
915 static char dump_nodes
[] =
916 "Usage: rpt nodes <nodename>\n"
917 " Dumps a list of directly and indirectly connected nodes to the console\n";
919 static char reload_usage
[] =
920 "Usage: rpt reload\n"
921 " Reloads app_rpt running config parameters\n";
923 static char restart_usage
[] =
924 "Usage: rpt restart\n"
925 " Restarts app_rpt\n";
927 static char fun_usage
[] =
928 "Usage: rpt fun <nodename> <command>\n"
929 " Send a DTMF function to a node\n";
932 static struct ast_cli_entry cli_debug
=
933 { { "rpt", "debug", "level" }, rpt_do_debug
,
934 "Enable app_rpt debugging", debug_usage
};
936 static struct ast_cli_entry cli_dump
=
937 { { "rpt", "dump" }, rpt_do_dump
,
938 "Dump app_rpt structs for debugging", dump_usage
};
940 static struct ast_cli_entry cli_stats
=
941 { { "rpt", "stats" }, rpt_do_stats
,
942 "Dump node statistics", dump_stats
};
944 static struct ast_cli_entry cli_nodes
=
945 { { "rpt", "nodes" }, rpt_do_nodes
,
946 "Dump node list", dump_nodes
};
948 static struct ast_cli_entry cli_lstats
=
949 { { "rpt", "lstats" }, rpt_do_lstats
,
950 "Dump link statistics", dump_lstats
};
952 static struct ast_cli_entry cli_reload
=
953 { { "rpt", "reload" }, rpt_do_reload
,
954 "Reload app_rpt config", reload_usage
};
956 static struct ast_cli_entry cli_restart
=
957 { { "rpt", "restart" }, rpt_do_restart
,
958 "Restart app_rpt", restart_usage
};
960 static struct ast_cli_entry cli_fun
=
961 { { "rpt", "fun" }, rpt_do_fun
,
962 "Execute a DTMF function", fun_usage
};
969 static struct telem_defaults tele_defs
[] = {
970 {"ct1","|t(350,0,100,3072)(500,0,100,3072)(660,0,100,3072)"},
971 {"ct2","|t(660,880,150,3072)"},
972 {"ct3","|t(440,0,150,3072)"},
973 {"ct4","|t(550,0,150,3072)"},
974 {"ct5","|t(660,0,150,3072)"},
975 {"ct6","|t(880,0,150,3072)"},
976 {"ct7","|t(660,440,150,3072)"},
977 {"ct8","|t(700,1100,150,3072)"},
978 {"remotemon","|t(1600,0,75,2048)"},
979 {"remotetx","|t(2000,0,75,2048)(0,0,75,0)(1600,0,75,2048)"},
980 {"cmdmode","|t(900,904,200,2048)"},
981 {"functcomplete","|t(1000,0,100,2048)(0,0,100,0)(1000,0,100,2048)"}
985 * Forward decl's - these suppress compiler warnings when funcs coded further down the file than thier invokation
988 static int setrbi(struct rpt
*myrpt
);
989 static int set_ft897(struct rpt
*myrpt
);
990 static int set_ic706(struct rpt
*myrpt
);
991 static int setkenwood(struct rpt
*myrpt
);
992 static int setrbi_check(struct rpt
*myrpt
);
997 * Define function protos for function table here
1000 static int function_ilink(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
);
1001 static int function_autopatchup(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
);
1002 static int function_autopatchdn(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
);
1003 static int function_status(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
);
1004 static int function_cop(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
);
1005 static int function_remote(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
);
1006 static int function_macro(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
);
1011 static struct function_table_tag function_table
[] = {
1012 {"cop", function_cop
},
1013 {"autopatchup", function_autopatchup
},
1014 {"autopatchdn", function_autopatchdn
},
1015 {"ilink", function_ilink
},
1016 {"status", function_status
},
1017 {"remote", function_remote
},
1018 {"macro", function_macro
}
1021 static long diskavail(struct rpt
*myrpt
)
1023 struct statfs statfsbuf
;
1025 if (!myrpt
->p
.archivedir
) return(0);
1026 if (statfs(myrpt
->p
.archivedir
,&statfsbuf
) == -1)
1028 ast_log(LOG_WARNING
,"Cannot get filesystem size for %s node %s\n",
1029 myrpt
->p
.archivedir
,myrpt
->name
);
1032 return(statfsbuf
.f_bavail
);
1035 static void do_dtmf_phone(struct rpt
*myrpt
, struct rpt_link
*mylink
, char c
)
1039 l
= myrpt
->links
.next
;
1040 /* go thru all the links */
1041 while(l
!= &myrpt
->links
)
1048 /* dont send to self */
1049 if (mylink
&& (l
== mylink
))
1054 if (l
->chan
) ast_senddigit(l
->chan
,c
);
1060 /* node logging function */
1061 static void donodelog(struct rpt
*myrpt
,char *str
)
1063 struct nodelog
*nodep
;
1066 if (!myrpt
->p
.archivedir
) return;
1067 nodep
= (struct nodelog
*)malloc(sizeof(struct nodelog
));
1070 ast_log(LOG_ERROR
,"Cannot get memory for node log");
1073 time(&nodep
->timestamp
);
1074 strncpy(nodep
->archivedir
,myrpt
->p
.archivedir
,
1075 sizeof(nodep
->archivedir
) - 1);
1076 strftime(datestr
,sizeof(datestr
) - 1,"%Y%m%d%H%M%S",
1077 localtime(&nodep
->timestamp
));
1078 snprintf(nodep
->str
,sizeof(nodep
->str
) - 1,"%s %s,%s\n",
1079 myrpt
->name
,datestr
,str
);
1080 ast_mutex_lock(&nodeloglock
);
1081 insque((struct qelem
*) nodep
, (struct qelem
*) nodelog
.prev
);
1082 ast_mutex_unlock(&nodeloglock
);
1085 /* must be called locked */
1086 static void do_dtmf_local(struct rpt
*myrpt
, char c
)
1090 static const char* dtmf_tones
[] = {
1091 "!941+1336/200,!0/200", /* 0 */
1092 "!697+1209/200,!0/200", /* 1 */
1093 "!697+1336/200,!0/200", /* 2 */
1094 "!697+1477/200,!0/200", /* 3 */
1095 "!770+1209/200,!0/200", /* 4 */
1096 "!770+1336/200,!0/200", /* 5 */
1097 "!770+1477/200,!0/200", /* 6 */
1098 "!852+1209/200,!0/200", /* 7 */
1099 "!852+1336/200,!0/200", /* 8 */
1100 "!852+1477/200,!0/200", /* 9 */
1101 "!697+1633/200,!0/200", /* A */
1102 "!770+1633/200,!0/200", /* B */
1103 "!852+1633/200,!0/200", /* C */
1104 "!941+1633/200,!0/200", /* D */
1105 "!941+1209/200,!0/200", /* * */
1106 "!941+1477/200,!0/200" }; /* # */
1111 snprintf(myrpt
->dtmf_local_str
+ strlen(myrpt
->dtmf_local_str
),sizeof(myrpt
->dtmf_local_str
) - 1,"%c",c
);
1112 if (!myrpt
->dtmf_local_timer
)
1113 myrpt
->dtmf_local_timer
= DTMF_LOCAL_STARTTIME
;
1116 if (myrpt
->dtmf_local_timer
== 1)
1118 /* if anything in the string */
1119 if (myrpt
->dtmf_local_str
[0])
1121 digit
= myrpt
->dtmf_local_str
[0];
1122 myrpt
->dtmf_local_str
[0] = 0;
1123 for(i
= 1; myrpt
->dtmf_local_str
[i
]; i
++)
1125 myrpt
->dtmf_local_str
[i
- 1] =
1126 myrpt
->dtmf_local_str
[i
];
1128 myrpt
->dtmf_local_str
[i
- 1] = 0;
1129 myrpt
->dtmf_local_timer
= DTMF_LOCAL_TIME
;
1130 rpt_mutex_unlock(&myrpt
->lock
);
1131 if (digit
>= '0' && digit
<='9')
1132 ast_playtones_start(myrpt
->txchannel
, 0, dtmf_tones
[digit
-'0'], 0);
1133 else if (digit
>= 'A' && digit
<= 'D')
1134 ast_playtones_start(myrpt
->txchannel
, 0, dtmf_tones
[digit
-'A'+10], 0);
1135 else if (digit
== '*')
1136 ast_playtones_start(myrpt
->txchannel
, 0, dtmf_tones
[14], 0);
1137 else if (digit
== '#')
1138 ast_playtones_start(myrpt
->txchannel
, 0, dtmf_tones
[15], 0);
1141 ast_log(LOG_DEBUG
, "Unable to generate DTMF tone '%c' for '%s'\n", digit
, myrpt
->txchannel
->name
);
1143 rpt_mutex_lock(&myrpt
->lock
);
1147 myrpt
->dtmf_local_timer
= 0;
1152 static int openserial(char *fname
)
1154 struct termios mode
;
1157 fd
= open(fname
,O_RDWR
);
1160 ast_log(LOG_WARNING
,"Cannot open serial port %s\n",fname
);
1163 memset(&mode
, 0, sizeof(mode
));
1164 if (tcgetattr(fd
, &mode
)) {
1165 ast_log(LOG_WARNING
, "Unable to get serial parameters on %s: %s\n", fname
, strerror(errno
));
1171 mode
.c_iflag
&= ~(IGNBRK
|BRKINT
|PARMRK
|ISTRIP
1172 |INLCR
|IGNCR
|ICRNL
|IXON
);
1173 mode
.c_oflag
&= ~OPOST
;
1174 mode
.c_lflag
&= ~(ECHO
|ECHONL
|ICANON
|ISIG
|IEXTEN
);
1175 mode
.c_cflag
&= ~(CSIZE
|PARENB
|CRTSCTS
);
1176 mode
.c_cflag
|= CS8
;
1177 mode
.c_cc
[TIME
] = 3;
1181 cfsetispeed(&mode
, B9600
);
1182 cfsetospeed(&mode
, B9600
);
1183 if (tcsetattr(fd
, TCSANOW
, &mode
))
1184 ast_log(LOG_WARNING
, "Unable to set serial parameters on %s: %s\n", fname
, strerror(errno
));
1188 static void mdc1200_notify(struct rpt
*myrpt
,char *fromnode
, unsigned int unit
)
1192 ast_verbose("Got MDC-1200 ID %04X from local system (%s)\n",
1197 ast_verbose("Got MDC-1200 ID %04X from node %s (%s)\n",
1198 unit
,fromnode
,myrpt
->name
);
1202 #ifdef _MDC_DECODE_H_
1204 static void mdc1200_send(struct rpt
*myrpt
, unsigned int unit
)
1207 struct ast_frame wf
;
1211 sprintf(str
,"I %s %04X",myrpt
->name
,unit
);
1213 wf
.frametype
= AST_FRAME_TEXT
;
1217 wf
.datalen
= strlen(str
) + 1;
1221 l
= myrpt
->links
.next
;
1222 /* otherwise, send it to all of em */
1223 while(l
!= &myrpt
->links
)
1225 if (l
->name
[0] == '0')
1231 if (l
->chan
) ast_write(l
->chan
,&wf
);
1239 static char func_xlat(struct rpt
*myrpt
,char c
,struct rpt_xlat
*xlat
)
1246 /* if too much time, reset the skate machine */
1247 if ((now
- xlat
->lastone
) > MAXXLATTIME
)
1249 xlat
->funcindex
= xlat
->endindex
= 0;
1251 if (xlat
->funccharseq
[0] && (c
== xlat
->funccharseq
[xlat
->funcindex
++]))
1253 time(&xlat
->lastone
);
1255 if (!xlat
->funccharseq
[xlat
->funcindex
])
1257 xlat
->funcindex
= xlat
->endindex
= 0;
1258 return(myrpt
->p
.funcchar
);
1260 } else xlat
->funcindex
= 0;
1261 if (xlat
->endcharseq
[0] && (c
== xlat
->endcharseq
[xlat
->endindex
++]))
1263 time(&xlat
->lastone
);
1265 if (!xlat
->endcharseq
[xlat
->endindex
])
1267 xlat
->funcindex
= xlat
->endindex
= 0;
1268 return(myrpt
->p
.endchar
);
1270 } else xlat
->endindex
= 0;
1271 /* if in middle of decode seq, send nothing back */
1272 if (gotone
) return(0);
1273 /* if no pass chars specified, return em all */
1274 if (!xlat
->passchars
[0]) return(c
);
1275 /* if a "pass char", pass it */
1276 if (strchr(xlat
->passchars
,c
)) return(c
);
1281 * Return a pointer to the first non-whitespace character
1284 static char *eatwhite(char *s
)
1286 while((*s
== ' ') || (*s
== 0x09)){ /* get rid of any leading white space */
1295 * Break up a delimited string into a table of substrings
1297 * str - delimited string ( will be modified )
1298 * strp- list of pointers to substrings (this is built by this function), NULL will be placed at end of list
1299 * limit- maximum number of substrings to process
1304 static int finddelim(char *str
, char *strp
[], int limit
)
1316 for(l
= 0; *str
&& (l
< limit
) ; str
++)
1318 if (*str
== QUOTECHR
)
1327 strp
[i
- 1] = str
+ 1;
1331 if ((*str
== DELIMCHR
) && (!inquo
))
1335 strp
[i
++] = str
+ 1;
1343 /* must be called locked */
1344 static void __mklinklist(struct rpt
*myrpt
, struct rpt_link
*mylink
, char *buf
)
1350 buf
[0] = 0; /* clear output buffer */
1351 /* go thru all links */
1352 for(l
= myrpt
->links
.next
; l
!= &myrpt
->links
; l
= l
->next
)
1354 /* if is not a real link, ignore it */
1355 if (l
->name
[0] == '0') continue;
1356 /* dont count our stuff */
1357 if (l
== mylink
) continue;
1358 if (mylink
&& (!strcmp(l
->name
,mylink
->name
))) continue;
1359 /* figure out mode to report */
1360 mode
= 'T'; /* use Tranceive by default */
1361 if (!l
->mode
) mode
= 'R'; /* indicate RX for our mode */
1362 if (!l
->thisconnected
) mode
= 'C'; /* indicate connecting */
1363 spos
= strlen(buf
); /* current buf size (b4 we add our stuff) */
1369 /* add nodes into buffer */
1372 snprintf(buf
+ spos
,MAXLINKLIST
- spos
,
1373 "%c%s,%s",mode
,l
->name
,l
->linklist
);
1375 else /* if no nodes, add this node into buffer */
1377 snprintf(buf
+ spos
,MAXLINKLIST
- spos
,
1378 "%c%s",mode
,l
->name
);
1380 /* if we are in tranceive mode, let all modes stand */
1381 if (mode
== 'T') continue;
1382 /* downgrade everyone on this node if appropriate */
1383 for(i
= spos
; buf
[i
]; i
++)
1385 if (buf
[i
] == 'T') buf
[i
] = mode
;
1386 if ((buf
[i
] == 'R') && (mode
== 'C')) buf
[i
] = mode
;
1392 /* must be called locked */
1393 static void __kickshort(struct rpt
*myrpt
)
1397 for(l
= myrpt
->links
.next
; l
!= &myrpt
->links
; l
= l
->next
)
1399 /* if is not a real link, ignore it */
1400 if (l
->name
[0] == '0') continue;
1401 l
->linklisttimer
= LINKLISTSHORTTIME
;
1406 static char *node_lookup(struct rpt
*myrpt
,char *digitbuf
)
1412 static time_t last
= 0;
1413 static struct ast_config
*ourcfg
= NULL
;
1414 struct ast_variable
*vp
;
1416 /* try to look it up locally first */
1417 val
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->p
.nodes
, digitbuf
);
1418 if (val
) return(val
);
1419 ast_mutex_lock(&nodelookuplock
);
1420 /* if file does not exist */
1421 if (stat(myrpt
->p
.extnodefile
,&mystat
) == -1)
1423 if (ourcfg
) ast_config_destroy(ourcfg
);
1425 ast_mutex_unlock(&nodelookuplock
);
1428 /* if we need to reload */
1429 if (mystat
.st_mtime
> last
)
1431 if (ourcfg
) ast_config_destroy(ourcfg
);
1432 ourcfg
= ast_config_load(myrpt
->p
.extnodefile
);
1433 /* if file not there, just bail */
1436 ast_mutex_unlock(&nodelookuplock
);
1439 /* reset "last" time */
1440 last
= mystat
.st_mtime
;
1442 /* determine longest node length again */
1444 vp
= ast_variable_browse(myrpt
->cfg
, myrpt
->p
.nodes
);
1446 j
= strlen(vp
->name
);
1447 if (j
> longestnode
)
1452 vp
= ast_variable_browse(ourcfg
, myrpt
->p
.extnodes
);
1454 j
= strlen(vp
->name
);
1455 if (j
> longestnode
)
1460 myrpt
->longestnode
= longestnode
;
1464 val
= (char *) ast_variable_retrieve(ourcfg
, myrpt
->p
.extnodes
, digitbuf
);
1465 ast_mutex_unlock(&nodelookuplock
);
1470 * Match a keyword in a list, and return index of string plus 1 if there was a match,* else return 0.
1471 * If param is passed in non-null, then it will be set to the first character past the match
1474 static int matchkeyword(char *string
, char **param
, char *keywords
[])
1477 for( i
= 0 ; keywords
[i
] ; i
++){
1478 ls
= strlen(keywords
[i
]);
1483 if(!strncmp(string
, keywords
[i
], ls
)){
1485 *param
= string
+ ls
;
1494 * Skip characters in string which are in charlist, and return a pointer to the
1495 * first non-matching character
1498 static char *skipchars(char *string
, char *charlist
)
1502 for(i
= 0; charlist
[i
] ; i
++){
1503 if(*string
== charlist
[i
]){
1516 static int myatoi(char *str
)
1520 if (str
== NULL
) return -1;
1521 /* leave this %i alone, non-base-10 input is useful here */
1522 if (sscanf(str
,"%i",&ret
) != 1) return -1;
1526 static int mycompar(const void *a
, const void *b
)
1528 char **x
= (char **) a
;
1529 char **y
= (char **) b
;
1532 if ((**x
< '0') || (**x
> '9')) xoff
= 1; else xoff
= 0;
1533 if ((**y
< '0') || (**y
> '9')) yoff
= 1; else yoff
= 0;
1534 return(strcmp((*x
) + xoff
,(*y
) + yoff
));
1539 /* rpt filter routine */
1540 static void rpt_filter(struct rpt
*myrpt
, volatile short *buf
, int len
)
1543 struct rptfilter
*f
;
1545 for(i
= 0; i
< len
; i
++)
1547 for(j
= 0; j
< MAXFILTERS
; j
++)
1549 f
= &myrpt
->filters
[j
];
1550 if (!*f
->desc
) continue;
1551 f
->x0
= f
->x1
; f
->x1
= f
->x2
;
1552 f
->x2
= ((float)buf
[i
]) / f
->gain
;
1553 f
->y0
= f
->y1
; f
->y1
= f
->y2
;
1554 f
->y2
= (f
->x0
+ f
->x2
) + f
->const0
* f
->x1
1555 + (f
->const1
* f
->y0
) + (f
->const2
* f
->y1
);
1556 buf
[i
] = (short)f
->y2
;
1565 Get the time for the machine's time zone
1566 Note: Asterisk requires a copy of localtime
1567 in the /etc directory for this to work properly.
1568 If /etc/localtime is not present, you will get
1569 GMT time! This is especially important on systems
1570 running embedded linux distributions as they don't usually
1571 have support for locales.
1573 If OLD_ASTERISK is defined, then the older localtime_r
1574 function will be used. The /etc/localtime file is not
1575 required in this case. This provides backward compatibility
1576 with Asterisk 1.2 systems.
1580 static void rpt_localtime( time_t * t
, struct tm
*lt
)
1585 ast_localtime(t
, lt
, NULL
);
1589 /* Retrieve an int from a config file */
1591 static int retrieve_astcfgint(struct rpt
*myrpt
,char *category
, char *name
, int min
, int max
, int defl
)
1595 char include_zero
= 0;
1597 if(min
< 0){ /* If min is negative, this means include 0 as a valid entry */
1602 var
= (char *) ast_variable_retrieve(myrpt
->cfg
, category
, name
);
1605 if(include_zero
&& !ret
)
1618 static void load_rpt_vars(int n
,int init
)
1621 int i
,j
,longestnode
;
1622 struct ast_variable
*vp
;
1623 struct ast_config
*cfg
;
1626 static char *cs_keywords
[] = {"rptena","rptdis","apena","apdis","lnkena","lnkdis","totena","totdis","skena","skdis",
1627 "ufena","ufdis","atena","atdis",NULL
};
1629 if (option_verbose
> 2)
1630 ast_verbose(VERBOSE_PREFIX_3
"%s config for repeater %s\n",
1631 (init
) ? "Loading initial" : "Re-Loading",rpt_vars
[n
].name
);
1632 ast_mutex_lock(&rpt_vars
[n
].lock
);
1633 if (rpt_vars
[n
].cfg
) ast_config_destroy(rpt_vars
[n
].cfg
);
1634 cfg
= ast_config_load("rpt.conf");
1636 ast_mutex_unlock(&rpt_vars
[n
].lock
);
1637 ast_log(LOG_NOTICE
, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
1640 rpt_vars
[n
].cfg
= cfg
;
1641 this = rpt_vars
[n
].name
;
1642 memset(&rpt_vars
[n
].p
,0,sizeof(rpt_vars
[n
].p
));
1645 /* clear all the fields in the structure after 'p' */
1646 memset(&rpt_vars
[n
].p
+ sizeof(rpt_vars
[0].p
), 0, sizeof(rpt_vars
[0]) - sizeof(rpt_vars
[0].p
) - offsetof(typeof(rpt_vars
[0]), p
));
1647 rpt_vars
[n
].tele
.next
= &rpt_vars
[n
].tele
;
1648 rpt_vars
[n
].tele
.prev
= &rpt_vars
[n
].tele
;
1649 rpt_vars
[n
].rpt_thread
= AST_PTHREADT_NULL
;
1650 rpt_vars
[n
].tailmessagen
= 0;
1653 /* zot out filters stuff */
1654 memset(&rpt_vars
[n
].filters
,0,sizeof(rpt_vars
[n
].filters
));
1656 val
= (char *) ast_variable_retrieve(cfg
,this,"context");
1657 if (val
) rpt_vars
[n
].p
.ourcontext
= val
;
1658 else rpt_vars
[n
].p
.ourcontext
= this;
1659 val
= (char *) ast_variable_retrieve(cfg
,this,"callerid");
1660 if (val
) rpt_vars
[n
].p
.ourcallerid
= val
;
1661 val
= (char *) ast_variable_retrieve(cfg
,this,"accountcode");
1662 if (val
) rpt_vars
[n
].p
.acctcode
= val
;
1663 val
= (char *) ast_variable_retrieve(cfg
,this,"idrecording");
1664 if (val
) rpt_vars
[n
].p
.ident
= val
;
1665 val
= (char *) ast_variable_retrieve(cfg
,this,"hangtime");
1666 if (val
) rpt_vars
[n
].p
.hangtime
= atoi(val
);
1667 else rpt_vars
[n
].p
.hangtime
= HANGTIME
;
1668 val
= (char *) ast_variable_retrieve(cfg
,this,"althangtime");
1669 if (val
) rpt_vars
[n
].p
.althangtime
= atoi(val
);
1670 else rpt_vars
[n
].p
.althangtime
= HANGTIME
;
1671 val
= (char *) ast_variable_retrieve(cfg
,this,"totime");
1672 if (val
) rpt_vars
[n
].p
.totime
= atoi(val
);
1673 else rpt_vars
[n
].p
.totime
= TOTIME
;
1674 rpt_vars
[n
].p
.tailmessagetime
= retrieve_astcfgint(&rpt_vars
[n
],this, "tailmessagetime", 0, 2400000, 0);
1675 rpt_vars
[n
].p
.tailsquashedtime
= retrieve_astcfgint(&rpt_vars
[n
],this, "tailsquashedtime", 0, 2400000, 0);
1676 rpt_vars
[n
].p
.duplex
= retrieve_astcfgint(&rpt_vars
[n
],this,"duplex",0,4,2);
1677 rpt_vars
[n
].p
.idtime
= retrieve_astcfgint(&rpt_vars
[n
],this, "idtime", -60000, 2400000, IDTIME
); /* Enforce a min max including zero */
1678 rpt_vars
[n
].p
.politeid
= retrieve_astcfgint(&rpt_vars
[n
],this, "politeid", 30000, 300000, POLITEID
); /* Enforce a min max */
1679 val
= (char *) ast_variable_retrieve(cfg
,this,"tonezone");
1680 if (val
) rpt_vars
[n
].p
.tonezone
= val
;
1681 rpt_vars
[n
].p
.tailmessages
[0] = 0;
1682 rpt_vars
[n
].p
.tailmessagemax
= 0;
1683 val
= (char *) ast_variable_retrieve(cfg
,this,"tailmessagelist");
1684 if (val
) rpt_vars
[n
].p
.tailmessagemax
= finddelim(val
, rpt_vars
[n
].p
.tailmessages
, 500);
1685 val
= (char *) ast_variable_retrieve(cfg
,this,"memory");
1686 if (!val
) val
= MEMORY
;
1687 rpt_vars
[n
].p
.memory
= val
;
1688 val
= (char *) ast_variable_retrieve(cfg
,this,"macro");
1689 if (!val
) val
= MACRO
;
1690 rpt_vars
[n
].p
.macro
= val
;
1691 val
= (char *) ast_variable_retrieve(cfg
,this,"startup_macro");
1692 if (val
) rpt_vars
[n
].p
.startupmacro
= val
;
1693 val
= (char *) ast_variable_retrieve(cfg
,this,"iobase");
1694 /* do not use atoi() here, we need to be able to have
1695 the input specified in hex or decimal so we use
1697 if ((!val
) || (sscanf(val
,"%i",&rpt_vars
[n
].p
.iobase
) != 1))
1698 rpt_vars
[n
].p
.iobase
= DEFAULT_IOBASE
;
1699 val
= (char *) ast_variable_retrieve(cfg
,this,"ioport");
1700 rpt_vars
[n
].p
.ioport
= val
;
1701 val
= (char *) ast_variable_retrieve(cfg
,this,"functions");
1705 rpt_vars
[n
].p
.simple
= 1;
1707 rpt_vars
[n
].p
.functions
= val
;
1708 val
= (char *) ast_variable_retrieve(cfg
,this,"link_functions");
1709 if (val
) rpt_vars
[n
].p
.link_functions
= val
;
1711 rpt_vars
[n
].p
.link_functions
= rpt_vars
[n
].p
.functions
;
1712 val
= (char *) ast_variable_retrieve(cfg
,this,"phone_functions");
1713 if (val
) rpt_vars
[n
].p
.phone_functions
= val
;
1714 val
= (char *) ast_variable_retrieve(cfg
,this,"dphone_functions");
1715 if (val
) rpt_vars
[n
].p
.dphone_functions
= val
;
1716 val
= (char *) ast_variable_retrieve(cfg
,this,"funcchar");
1717 if (!val
) rpt_vars
[n
].p
.funcchar
= FUNCCHAR
; else
1718 rpt_vars
[n
].p
.funcchar
= *val
;
1719 val
= (char *) ast_variable_retrieve(cfg
,this,"endchar");
1720 if (!val
) rpt_vars
[n
].p
.endchar
= ENDCHAR
; else
1721 rpt_vars
[n
].p
.endchar
= *val
;
1722 val
= (char *) ast_variable_retrieve(cfg
,this,"nobusyout");
1723 if (val
) rpt_vars
[n
].p
.nobusyout
= ast_true(val
);
1724 val
= (char *) ast_variable_retrieve(cfg
,this,"notelemtx");
1725 if (val
) rpt_vars
[n
].p
.notelemtx
= ast_true(val
);
1726 val
= (char *) ast_variable_retrieve(cfg
,this,"propagate_dtmf");
1727 if (val
) rpt_vars
[n
].p
.propagate_dtmf
= ast_true(val
);
1728 val
= (char *) ast_variable_retrieve(cfg
,this,"propagate_phonedtmf");
1729 if (val
) rpt_vars
[n
].p
.propagate_phonedtmf
= ast_true(val
);
1730 val
= (char *) ast_variable_retrieve(cfg
,this,"linktolink");
1731 if (val
) rpt_vars
[n
].p
.linktolink
= ast_true(val
);
1732 val
= (char *) ast_variable_retrieve(cfg
,this,"nodes");
1733 if (!val
) val
= NODES
;
1734 rpt_vars
[n
].p
.nodes
= val
;
1735 val
= (char *) ast_variable_retrieve(cfg
,this,"extnodes");
1736 if (!val
) val
= EXTNODES
;
1737 rpt_vars
[n
].p
.extnodes
= val
;
1738 val
= (char *) ast_variable_retrieve(cfg
,this,"extnodefile");
1739 if (!val
) val
= EXTNODEFILE
;
1740 rpt_vars
[n
].p
.extnodefile
= val
;
1741 val
= (char *) ast_variable_retrieve(cfg
,this,"archivedir");
1742 if (val
) rpt_vars
[n
].p
.archivedir
= val
;
1743 val
= (char *) ast_variable_retrieve(cfg
,this,"authlevel");
1744 if (val
) rpt_vars
[n
].p
.authlevel
= atoi(val
);
1745 else rpt_vars
[n
].p
.authlevel
= 0;
1746 val
= (char *) ast_variable_retrieve(cfg
,this,"monminblocks");
1747 if (val
) rpt_vars
[n
].p
.monminblocks
= atol(val
);
1748 else rpt_vars
[n
].p
.monminblocks
= DEFAULT_MONITOR_MIN_DISK_BLOCKS
;
1749 val
= (char *) ast_variable_retrieve(cfg
,this,"remote_inact_timeout");
1750 if (val
) rpt_vars
[n
].p
.remoteinacttimeout
= atoi(val
);
1751 else rpt_vars
[n
].p
.remoteinacttimeout
= DEFAULT_REMOTE_INACT_TIMEOUT
;
1752 val
= (char *) ast_variable_retrieve(cfg
,this,"civaddr");
1753 if (val
) rpt_vars
[n
].p
.civaddr
= atoi(val
);
1754 else rpt_vars
[n
].p
.civaddr
= DEFAULT_CIV_ADDR
;
1755 val
= (char *) ast_variable_retrieve(cfg
,this,"remote_timeout");
1756 if (val
) rpt_vars
[n
].p
.remotetimeout
= atoi(val
);
1757 else rpt_vars
[n
].p
.remotetimeout
= DEFAULT_REMOTE_TIMEOUT
;
1758 val
= (char *) ast_variable_retrieve(cfg
,this,"remote_timeout_warning");
1759 if (val
) rpt_vars
[n
].p
.remotetimeoutwarning
= atoi(val
);
1760 else rpt_vars
[n
].p
.remotetimeoutwarning
= DEFAULT_REMOTE_TIMEOUT_WARNING
;
1761 val
= (char *) ast_variable_retrieve(cfg
,this,"remote_timeout_warning_freq");
1762 if (val
) rpt_vars
[n
].p
.remotetimeoutwarningfreq
= atoi(val
);
1763 else rpt_vars
[n
].p
.remotetimeoutwarningfreq
= DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ
;
1765 val
= (char *) ast_variable_retrieve(cfg
,this,"rxnotch");
1767 i
= finddelim(val
,strs
,MAXFILTERS
* 2);
1768 i
&= ~1; /* force an even number, rounded down */
1769 if (i
>= 2) for(j
= 0; j
< i
; j
+= 2)
1771 rpt_mknotch(atof(strs
[j
]),atof(strs
[j
+ 1]),
1772 &rpt_vars
[n
].filters
[j
>> 1].gain
,
1773 &rpt_vars
[n
].filters
[j
>> 1].const0
,
1774 &rpt_vars
[n
].filters
[j
>> 1].const1
,
1775 &rpt_vars
[n
].filters
[j
>> 1].const2
);
1776 sprintf(rpt_vars
[n
].filters
[j
>> 1].desc
,"%s Hz, BW = %s",
1777 strs
[j
],strs
[j
+ 1]);
1782 val
= (char *) ast_variable_retrieve(cfg
,this,"inxlat");
1784 memset(&rpt_vars
[n
].p
.inxlat
,0,sizeof(struct rpt_xlat
));
1785 i
= finddelim(val
,strs
,3);
1786 if (i
) strncpy(rpt_vars
[n
].p
.inxlat
.funccharseq
,strs
[0],MAXXLAT
- 1);
1787 if (i
> 1) strncpy(rpt_vars
[n
].p
.inxlat
.endcharseq
,strs
[1],MAXXLAT
- 1);
1788 if (i
> 2) strncpy(rpt_vars
[n
].p
.inxlat
.passchars
,strs
[2],MAXXLAT
- 1);
1790 val
= (char *) ast_variable_retrieve(cfg
,this,"outxlat");
1792 memset(&rpt_vars
[n
].p
.outxlat
,0,sizeof(struct rpt_xlat
));
1793 i
= finddelim(val
,strs
,3);
1794 if (i
) strncpy(rpt_vars
[n
].p
.outxlat
.funccharseq
,strs
[0],MAXXLAT
- 1);
1795 if (i
> 1) strncpy(rpt_vars
[n
].p
.outxlat
.endcharseq
,strs
[1],MAXXLAT
- 1);
1796 if (i
> 2) strncpy(rpt_vars
[n
].p
.outxlat
.passchars
,strs
[2],MAXXLAT
- 1);
1798 /* retreive the stanza name for the control states if there is one */
1799 val
= (char *) ast_variable_retrieve(cfg
,this,"controlstates");
1800 rpt_vars
[n
].p
.csstanzaname
= val
;
1802 /* retreive the stanza name for the scheduler if there is one */
1803 val
= (char *) ast_variable_retrieve(cfg
,this,"scheduler");
1804 rpt_vars
[n
].p
.skedstanzaname
= val
;
1806 /* retreive the stanza name for the txlimits */
1807 val
= (char *) ast_variable_retrieve(cfg
,this,"txlimits");
1808 rpt_vars
[n
].p
.txlimitsstanzaname
= val
;
1812 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.nodes
);
1815 j
= strlen(vp
->name
);
1816 if (j
> longestnode
)
1821 rpt_vars
[n
].longestnode
= longestnode
;
1824 * For this repeater, Determine the length of the longest function
1826 rpt_vars
[n
].longestfunc
= 0;
1827 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.functions
);
1829 j
= strlen(vp
->name
);
1830 if (j
> rpt_vars
[n
].longestfunc
)
1831 rpt_vars
[n
].longestfunc
= j
;
1835 * For this repeater, Determine the length of the longest function
1837 rpt_vars
[n
].link_longestfunc
= 0;
1838 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.link_functions
);
1840 j
= strlen(vp
->name
);
1841 if (j
> rpt_vars
[n
].link_longestfunc
)
1842 rpt_vars
[n
].link_longestfunc
= j
;
1845 rpt_vars
[n
].phone_longestfunc
= 0;
1846 if (rpt_vars
[n
].p
.phone_functions
)
1848 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.phone_functions
);
1850 j
= strlen(vp
->name
);
1851 if (j
> rpt_vars
[n
].phone_longestfunc
)
1852 rpt_vars
[n
].phone_longestfunc
= j
;
1856 rpt_vars
[n
].dphone_longestfunc
= 0;
1857 if (rpt_vars
[n
].p
.dphone_functions
)
1859 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.dphone_functions
);
1861 j
= strlen(vp
->name
);
1862 if (j
> rpt_vars
[n
].dphone_longestfunc
)
1863 rpt_vars
[n
].dphone_longestfunc
= j
;
1867 rpt_vars
[n
].macro_longest
= 1;
1868 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.macro
);
1870 j
= strlen(vp
->name
);
1871 if (j
> rpt_vars
[n
].macro_longest
)
1872 rpt_vars
[n
].macro_longest
= j
;
1876 /* Browse for control states */
1877 if(rpt_vars
[n
].p
.csstanzaname
)
1878 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.csstanzaname
);
1881 for( i
= 0 ; vp
&& (i
< MAX_SYSSTATES
) ; i
++){ /* Iterate over the number of control state lines in the stanza */
1882 int k
,nukw
,statenum
;
1883 statenum
=atoi(vp
->name
);
1884 strncpy(s1
, vp
->value
, 255);
1886 nukw
= finddelim(s1
,strs
,32);
1888 for (k
= 0 ; k
< nukw
; k
++){ /* for each user specified keyword */
1889 for(j
= 0 ; cs_keywords
[j
] != NULL
; j
++){ /* try to match to one in our internal table */
1890 if(!strcmp(strs
[k
],cs_keywords
[j
])){
1892 case 0: /* rptena */
1893 rpt_vars
[n
].p
.s
[statenum
].txdisable
= 0;
1895 case 1: /* rptdis */
1896 rpt_vars
[n
].p
.s
[statenum
].txdisable
= 1;
1900 rpt_vars
[n
].p
.s
[statenum
].autopatchdisable
= 0;
1904 rpt_vars
[n
].p
.s
[statenum
].autopatchdisable
= 1;
1907 case 4: /* lnkena */
1908 rpt_vars
[n
].p
.s
[statenum
].linkfundisable
= 0;
1911 case 5: /* lnkdis */
1912 rpt_vars
[n
].p
.s
[statenum
].linkfundisable
= 1;
1915 case 6: /* totena */
1916 rpt_vars
[n
].p
.s
[statenum
].totdisable
= 0;
1919 case 7: /* totdis */
1920 rpt_vars
[n
].p
.s
[statenum
].totdisable
= 1;
1924 rpt_vars
[n
].p
.s
[statenum
].schedulerdisable
= 0;
1928 rpt_vars
[n
].p
.s
[statenum
].schedulerdisable
= 1;
1931 case 10: /* ufena */
1932 rpt_vars
[n
].p
.s
[statenum
].userfundisable
= 0;
1935 case 11: /* ufdis */
1936 rpt_vars
[n
].p
.s
[statenum
].userfundisable
= 1;
1939 case 12: /* atena */
1940 rpt_vars
[n
].p
.s
[statenum
].alternatetail
= 1;
1943 case 13: /* atdis */
1944 rpt_vars
[n
].p
.s
[statenum
].alternatetail
= 0;
1948 ast_log(LOG_WARNING
,
1949 "Unhandled control state keyword %s", cs_keywords
[i
]);
1957 ast_mutex_unlock(&rpt_vars
[n
].lock
);
1961 * Enable or disable debug output at a given level at the console
1964 static int rpt_do_debug(int fd
, int argc
, char *argv
[])
1969 return RESULT_SHOWUSAGE
;
1970 newlevel
= myatoi(argv
[3]);
1971 if((newlevel
< 0) || (newlevel
> 7))
1972 return RESULT_SHOWUSAGE
;
1974 ast_cli(fd
, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug
, newlevel
);
1976 ast_cli(fd
, "app_rpt Debugging disabled\n");
1979 return RESULT_SUCCESS
;
1983 * Dump rpt struct debugging onto console
1986 static int rpt_do_dump(int fd
, int argc
, char *argv
[])
1991 return RESULT_SHOWUSAGE
;
1993 for(i
= 0; i
< nrpts
; i
++)
1995 if (!strcmp(argv
[2],rpt_vars
[i
].name
))
1997 rpt_vars
[i
].disgorgetime
= time(NULL
) + 10; /* Do it 10 seconds later */
1998 ast_cli(fd
, "app_rpt struct dump requested for node %s\n",argv
[2]);
1999 return RESULT_SUCCESS
;
2002 return RESULT_FAILURE
;
2006 * Dump statistics onto console
2009 static int rpt_do_stats(int fd
, int argc
, char *argv
[])
2012 int dailytxtime
, dailykerchunks
;
2013 int totalkerchunks
, dailykeyups
, totalkeyups
, timeouts
;
2014 int totalexecdcommands
, dailyexecdcommands
, hours
, minutes
, seconds
;
2015 long long totaltxtime
;
2017 char *listoflinks
[MAX_STAT_LINKS
];
2018 char *lastnodewhichkeyedusup
, *lastdtmfcommand
;
2019 char *tot_state
, *ider_state
, *patch_state
;
2020 char *reverse_patch_state
, *sys_ena
, *tot_ena
, *link_ena
, *patch_ena
;
2021 char *sch_ena
, *input_signal
, *called_number
, *user_funs
, *tail_type
;
2024 static char *not_applicable
= "N/A";
2027 return RESULT_SHOWUSAGE
;
2029 for(i
= 0 ; i
< MAX_STAT_LINKS
; i
++)
2030 listoflinks
[i
] = NULL
;
2032 tot_state
= ider_state
=
2033 patch_state
= reverse_patch_state
=
2034 input_signal
= called_number
=
2035 lastdtmfcommand
= not_applicable
;
2037 for(i
= 0; i
< nrpts
; i
++)
2039 if (!strcmp(argv
[2],rpt_vars
[i
].name
)){
2040 /* Make a copy of all stat variables while locked */
2041 myrpt
= &rpt_vars
[i
];
2042 rpt_mutex_lock(&myrpt
->lock
); /* LOCK */
2044 dailytxtime
= myrpt
->dailytxtime
;
2045 totaltxtime
= myrpt
->totaltxtime
;
2046 dailykeyups
= myrpt
->dailykeyups
;
2047 totalkeyups
= myrpt
->totalkeyups
;
2048 dailykerchunks
= myrpt
->dailykerchunks
;
2049 totalkerchunks
= myrpt
->totalkerchunks
;
2050 dailyexecdcommands
= myrpt
->dailyexecdcommands
;
2051 totalexecdcommands
= myrpt
->totalexecdcommands
;
2052 timeouts
= myrpt
->timeouts
;
2054 /* Traverse the list of connected nodes */
2055 reverse_patch_state
= "DOWN";
2057 l
= myrpt
->links
.next
;
2058 while(l
&& (l
!= &myrpt
->links
)){
2059 if (l
->name
[0] == '0'){ /* Skip '0' nodes */
2060 reverse_patch_state
= "UP";
2064 listoflinks
[j
] = ast_strdupa(l
->name
);
2070 lastnodewhichkeyedusup
= ast_strdupa(myrpt
->lastnodewhichkeyedusup
);
2071 if((!lastnodewhichkeyedusup
) || (!strlen(lastnodewhichkeyedusup
)))
2072 lastnodewhichkeyedusup
= not_applicable
;
2075 input_signal
= "YES";
2077 input_signal
= "NO";
2079 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
)
2080 sys_ena
= "DISABLED";
2082 sys_ena
= "ENABLED";
2084 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].totdisable
)
2085 tot_ena
= "DISABLED";
2087 tot_ena
= "ENABLED";
2089 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].linkfundisable
)
2090 link_ena
= "DISABLED";
2092 link_ena
= "ENABLED";
2094 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].autopatchdisable
)
2095 patch_ena
= "DISABLED";
2097 patch_ena
= "ENABLED";
2099 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].schedulerdisable
)
2100 sch_ena
= "DISABLED";
2102 sch_ena
= "ENABLED";
2104 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].userfundisable
)
2105 user_funs
= "DISABLED";
2107 user_funs
= "ENABLED";
2109 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].alternatetail
)
2110 tail_type
= "ALTERNATE";
2112 tail_type
= "STANDARD";
2115 tot_state
= "TIMED OUT!";
2116 else if(myrpt
->totimer
!= myrpt
->p
.totime
)
2117 tot_state
= "ARMED";
2119 tot_state
= "RESET";
2122 ider_state
= "QUEUED IN TAIL";
2123 else if(myrpt
->mustid
)
2124 ider_state
= "QUEUED FOR CLEANUP";
2126 ider_state
= "CLEAN";
2128 switch(myrpt
->callmode
){
2130 patch_state
= "DIALING";
2133 patch_state
= "CONNECTING";
2140 patch_state
= "CALL FAILED";
2144 patch_state
= "DOWN";
2147 if(strlen(myrpt
->exten
)){
2148 called_number
= ast_strdupa(myrpt
->exten
);
2150 called_number
= not_applicable
;
2153 if(strlen(myrpt
->lastdtmfcommand
)){
2154 lastdtmfcommand
= ast_strdupa(myrpt
->lastdtmfcommand
);
2155 if(!lastdtmfcommand
)
2156 lastdtmfcommand
= not_applicable
;
2159 rpt_mutex_unlock(&myrpt
->lock
); /* UNLOCK */
2161 ast_cli(fd
, "************************ NODE %s STATISTICS *************************\n\n", myrpt
->name
);
2162 ast_cli(fd
, "Selected system state............................: %d\n", myrpt
->p
.sysstate_cur
);
2163 ast_cli(fd
, "Signal on input..................................: %s\n", input_signal
);
2164 ast_cli(fd
, "System...........................................: %s\n", sys_ena
);
2165 ast_cli(fd
, "Scheduler........................................: %s\n", sch_ena
);
2166 ast_cli(fd
, "Tail Time........................................: %s\n", tail_type
);
2167 ast_cli(fd
, "Time out timer...................................: %s\n", tot_ena
);
2168 ast_cli(fd
, "Time out timer state.............................: %s\n", tot_state
);
2169 ast_cli(fd
, "Time outs since system initialization............: %d\n", timeouts
);
2170 ast_cli(fd
, "Identifier state.................................: %s\n", ider_state
);
2171 ast_cli(fd
, "Kerchunks today..................................: %d\n", dailykerchunks
);
2172 ast_cli(fd
, "Kerchunks since system initialization............: %d\n", totalkerchunks
);
2173 ast_cli(fd
, "Keyups today.....................................: %d\n", dailykeyups
);
2174 ast_cli(fd
, "Keyups since system initialization...............: %d\n", totalkeyups
);
2175 ast_cli(fd
, "DTMF commands today..............................: %d\n", dailyexecdcommands
);
2176 ast_cli(fd
, "DTMF commands since system initialization........: %d\n", totalexecdcommands
);
2177 ast_cli(fd
, "Last DTMF command executed.......................: %s\n", lastdtmfcommand
);
2178 hours
= dailytxtime
/3600000;
2179 dailytxtime
%= 3600000;
2180 minutes
= dailytxtime
/60000;
2181 dailytxtime
%= 60000;
2182 seconds
= dailytxtime
/1000;
2183 dailytxtime
%= 1000;
2185 ast_cli(fd
, "TX time today ...................................: %02d:%02d:%02d.%d\n",
2186 hours
, minutes
, seconds
, dailytxtime
);
2188 hours
= (int) totaltxtime
/3600000;
2189 totaltxtime
%= 3600000;
2190 minutes
= (int) totaltxtime
/60000;
2191 totaltxtime
%= 60000;
2192 seconds
= (int) totaltxtime
/1000;
2193 totaltxtime
%= 1000;
2195 ast_cli(fd
, "TX time since system initialization..............: %02d:%02d:%02d.%d\n",
2196 hours
, minutes
, seconds
, (int) totaltxtime
);
2197 ast_cli(fd
, "Nodes currently connected to us..................: ");
2199 if(!listoflinks
[j
]){
2201 ast_cli(fd
,"<NONE>");
2205 ast_cli(fd
, "%s", listoflinks
[j
]);
2211 if(listoflinks
[j
+ 1])
2217 ast_cli(fd
, "Last node which transmitted to us................: %s\n", lastnodewhichkeyedusup
);
2218 ast_cli(fd
, "Autopatch........................................: %s\n", patch_ena
);
2219 ast_cli(fd
, "Autopatch state..................................: %s\n", patch_state
);
2220 ast_cli(fd
, "Autopatch called number..........................: %s\n", called_number
);
2221 ast_cli(fd
, "Reverse patch/IAXRPT connected...................: %s\n", reverse_patch_state
);
2222 ast_cli(fd
, "User linking commands............................: %s\n", link_ena
);
2223 ast_cli(fd
, "User functions...................................: %s\n\n", user_funs
);
2224 return RESULT_SUCCESS
;
2227 return RESULT_FAILURE
;
2231 * Link stats function
2234 static int rpt_do_lstats(int fd
, int argc
, char *argv
[])
2240 struct rpt_lstat
*s
,*t
;
2241 struct rpt_lstat s_head
;
2243 return RESULT_SHOWUSAGE
;
2246 s_head
.next
= &s_head
;
2247 s_head
.prev
= &s_head
;
2249 for(i
= 0; i
< nrpts
; i
++)
2251 if (!strcmp(argv
[2],rpt_vars
[i
].name
)){
2252 /* Make a copy of all stat variables while locked */
2253 myrpt
= &rpt_vars
[i
];
2254 rpt_mutex_lock(&myrpt
->lock
); /* LOCK */
2255 /* Traverse the list of connected nodes */
2257 l
= myrpt
->links
.next
;
2258 while(l
&& (l
!= &myrpt
->links
)){
2259 if (l
->name
[0] == '0'){ /* Skip '0' nodes */
2263 if((s
= (struct rpt_lstat
*) malloc(sizeof(struct rpt_lstat
))) == NULL
){
2264 ast_log(LOG_ERROR
, "Malloc failed in rpt_do_lstats\n");
2265 rpt_mutex_unlock(&myrpt
->lock
); /* UNLOCK */
2266 return RESULT_FAILURE
;
2268 memset(s
, 0, sizeof(struct rpt_lstat
));
2269 strncpy(s
->name
, l
->name
, MAXREMSTR
- 1);
2270 if (l
->chan
) pbx_substitute_variables_helper(l
->chan
, "${IAXPEER(CURRENTCHANNEL)}", s
->peer
, MAXPEERSTR
- 1);
2271 else strcpy(s
->peer
,"(none)");
2273 s
->outbound
= l
->outbound
;
2274 s
->reconnects
= l
->reconnects
;
2275 s
->connecttime
= l
->connecttime
;
2276 s
->thisconnected
= l
->thisconnected
;
2277 memcpy(s
->chan_stat
,l
->chan_stat
,NRPTSTAT
* sizeof(struct rpt_chan_stat
));
2278 insque((struct qelem
*) s
, (struct qelem
*) s_head
.next
);
2279 memset(l
->chan_stat
,0,NRPTSTAT
* sizeof(struct rpt_chan_stat
));
2282 rpt_mutex_unlock(&myrpt
->lock
); /* UNLOCK */
2283 ast_cli(fd
, "NODE PEER RECONNECTS DIRECTION CONNECT TIME CONNECT STATE\n");
2284 ast_cli(fd
, "---- ---- ---------- --------- ------------ -------------\n");
2286 for(s
= s_head
.next
; s
!= &s_head
; s
= s
->next
){
2287 int hours
, minutes
, seconds
;
2288 long long connecttime
= s
->connecttime
;
2290 hours
= (int) connecttime
/3600000;
2291 connecttime
%= 3600000;
2292 minutes
= (int) connecttime
/60000;
2293 connecttime
%= 60000;
2294 seconds
= (int) connecttime
/1000;
2295 connecttime
%= 1000;
2296 snprintf(conntime
, 20, "%02d:%02d:%02d.%d",
2297 hours
, minutes
, seconds
, (int) connecttime
);
2299 if(s
->thisconnected
)
2300 connstate
= "ESTABLISHED";
2302 connstate
= "CONNECTING";
2303 ast_cli(fd
, "%-10s%-20s%-12d%-11s%-20s%-20s\n",
2304 s
->name
, s
->peer
, s
->reconnects
, (s
->outbound
)? "OUT":"IN", conntime
, connstate
);
2306 /* destroy our local link queue */
2308 while(s
!= &s_head
){
2311 remque((struct qelem
*)t
);
2314 return RESULT_SUCCESS
;
2317 return RESULT_FAILURE
;
2321 * List all nodes connected, directly or indirectly
2324 static int rpt_do_nodes(int fd
, int argc
, char *argv
[])
2328 char lbuf
[MAXLINKLIST
],*strs
[MAXLINKLIST
];
2331 return RESULT_SHOWUSAGE
;
2333 for(i
= 0; i
< nrpts
; i
++)
2335 if (!strcmp(argv
[2],rpt_vars
[i
].name
)){
2336 /* Make a copy of all stat variables while locked */
2337 myrpt
= &rpt_vars
[i
];
2338 rpt_mutex_lock(&myrpt
->lock
); /* LOCK */
2339 __mklinklist(myrpt
,NULL
,lbuf
);
2340 rpt_mutex_unlock(&myrpt
->lock
); /* UNLOCK */
2342 ns
= finddelim(lbuf
,strs
,MAXLINKLIST
);
2344 if (ns
) qsort((void *)strs
,ns
,sizeof(char *),mycompar
);
2346 ast_cli(fd
, "************************* CONNECTED NODES *************************\n\n");
2350 ast_cli(fd
,"<NONE>");
2354 ast_cli(fd
, "%s", strs
[j
]);
2364 return RESULT_SUCCESS
;
2367 return RESULT_FAILURE
;
2374 static int rpt_do_reload(int fd
, int argc
, char *argv
[])
2378 if (argc
> 2) return RESULT_SHOWUSAGE
;
2380 for(n
= 0; n
< nrpts
; n
++) rpt_vars
[n
].reload
= 1;
2382 return RESULT_FAILURE
;
2389 static int rpt_do_restart(int fd
, int argc
, char *argv
[])
2393 if (argc
> 2) return RESULT_SHOWUSAGE
;
2394 for(i
= 0; i
< nrpts
; i
++)
2396 if (rpt_vars
[i
].rxchannel
) ast_softhangup(rpt_vars
[i
].rxchannel
,AST_SOFTHANGUP_DEV
);
2398 return RESULT_FAILURE
;
2403 * send an app_rpt DTMF function from the CLI
2406 static int rpt_do_fun(int fd
, int argc
, char *argv
[])
2410 if (argc
!= 4) return RESULT_SHOWUSAGE
;
2412 for(i
= 0; i
< nrpts
; i
++){
2413 if(!strcmp(argv
[2], rpt_vars
[i
].name
)){
2414 struct rpt
*myrpt
= &rpt_vars
[i
];
2415 rpt_mutex_lock(&myrpt
->lock
);
2416 if ((MAXMACRO
- strlen(myrpt
->macrobuf
)) < strlen(argv
[3])){
2417 rpt_mutex_unlock(&myrpt
->lock
);
2421 myrpt
->macrotimer
= MACROTIME
;
2422 strncat(myrpt
->macrobuf
, argv
[3], MAXMACRO
- strlen(myrpt
->macrobuf
) - 1);
2424 rpt_mutex_unlock(&myrpt
->lock
);
2428 ast_cli(fd
, "Function decoder busy");
2430 return RESULT_FAILURE
;
2435 static int play_tone_pair(struct ast_channel
*chan
, int f1
, int f2
, int duration
, int amplitude
)
2439 if ((res
= ast_tonepair_start(chan
, f1
, f2
, duration
, amplitude
)))
2442 while(chan
->generatordata
) {
2443 if (ast_safe_sleep(chan
,1)) return -1;
2449 static int play_tone(struct ast_channel
*chan
, int freq
, int duration
, int amplitude
)
2451 return play_tone_pair(chan
, freq
, 0, duration
, amplitude
);
2454 static int play_silence(struct ast_channel
*chan
, int duration
)
2456 return play_tone_pair(chan
, 0, 0, duration
, 0);
2460 static int send_morse(struct ast_channel
*chan
, char *string
, int speed
, int freq
, int amplitude
)
2463 static struct morse_bits mbits
[] = {
2528 int intralettertime
;
2529 int interlettertime
;
2539 /* Approximate the dot time from the speed arg. */
2541 dottime
= 900/speed
;
2543 /* Establish timing releationships */
2545 dashtime
= 3 * dottime
;
2546 intralettertime
= dottime
;
2547 interlettertime
= dottime
* 4 ;
2548 interwordtime
= dottime
* 7;
2550 for(;(*string
) && (!res
); string
++){
2554 /* Convert lower case to upper case */
2556 if((c
>= 'a') && (c
<= 'z'))
2559 /* Can't deal with any char code greater than Z, skip it */
2564 /* If space char, wait the inter word time */
2568 res
= play_silence(chan
, interwordtime
);
2572 /* Subtract out control char offset to match our table */
2576 /* Get the character data */
2579 ddcomb
= mbits
[c
].ddcomb
;
2581 /* Send the character */
2585 res
= play_tone(chan
, freq
, (ddcomb
& 1) ? dashtime
: dottime
, amplitude
);
2587 res
= play_silence(chan
, intralettertime
);
2591 /* Wait the interletter time */
2594 res
= play_silence(chan
, interlettertime
- intralettertime
);
2597 /* Wait for all the frames to be sent */
2600 res
= ast_waitstream(chan
, "");
2601 ast_stopstream(chan
);
2604 * Wait for the zaptel driver to physically write the tone blocks to the hardware
2607 for(i
= 0; i
< 20 ; i
++){
2608 flags
= DAHDI_IOMUX_WRITEEMPTY
| DAHDI_IOMUX_NOWAIT
;
2609 res
= ioctl(chan
->fds
[0], DAHDI_IOMUX
, &flags
);
2610 if(flags
& DAHDI_IOMUX_WRITEEMPTY
)
2612 if( ast_safe_sleep(chan
, 50)){
2622 static int send_tone_telemetry(struct ast_channel
*chan
, char *tonestring
)
2635 stringp
= ast_strdupa(tonestring
);
2638 tonesubset
= strsep(&stringp
,")");
2641 if(sscanf(tonesubset
,"(%d,%d,%d,%d", &f1
, &f2
, &duration
, &litude
) != 4)
2643 res
= play_tone_pair(chan
, f1
, f2
, duration
, amplitude
);
2648 res
= play_tone_pair(chan
, 0, 0, 100, 0); /* This is needed to ensure the last tone segment is timed correctly */
2651 res
= ast_waitstream(chan
, "");
2652 ast_stopstream(chan
);
2655 * Wait for the zaptel driver to physically write the tone blocks to the hardware
2658 for(i
= 0; i
< 20 ; i
++){
2659 flags
= DAHDI_IOMUX_WRITEEMPTY
| DAHDI_IOMUX_NOWAIT
;
2660 res
= ioctl(chan
->fds
[0], DAHDI_IOMUX
, &flags
);
2661 if(flags
& DAHDI_IOMUX_WRITEEMPTY
)
2663 if( ast_safe_sleep(chan
, 50)){
2673 static int sayfile(struct ast_channel
*mychannel
,char *fname
)
2677 res
= ast_streamfile(mychannel
, fname
, mychannel
->language
);
2679 res
= ast_waitstream(mychannel
, "");
2681 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
2682 ast_stopstream(mychannel
);
2686 static int saycharstr(struct ast_channel
*mychannel
,char *str
)
2690 res
= ast_say_character_str(mychannel
,str
,NULL
,mychannel
->language
);
2692 res
= ast_waitstream(mychannel
, "");
2694 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
2695 ast_stopstream(mychannel
);
2699 static int saynum(struct ast_channel
*mychannel
, int num
)
2702 res
= ast_say_number(mychannel
, num
, NULL
, mychannel
->language
, NULL
);
2704 res
= ast_waitstream(mychannel
, "");
2706 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
2707 ast_stopstream(mychannel
);
2712 static int telem_any(struct rpt
*myrpt
,struct ast_channel
*chan
, char *entry
)
2717 static int morsespeed
;
2718 static int morsefreq
;
2719 static int morseampl
;
2720 static int morseidfreq
= 0;
2721 static int morseidampl
;
2722 static char mcat
[] = MORSE
;
2726 if(!morseidfreq
){ /* Get the morse parameters if not already loaded */
2727 morsespeed
= retrieve_astcfgint(myrpt
, mcat
, "speed", 5, 20, 20);
2728 morsefreq
= retrieve_astcfgint(myrpt
, mcat
, "frequency", 300, 3000, 800);
2729 morseampl
= retrieve_astcfgint(myrpt
, mcat
, "amplitude", 200, 8192, 4096);
2730 morseidampl
= retrieve_astcfgint(myrpt
, mcat
, "idamplitude", 200, 8192, 2048);
2731 morseidfreq
= retrieve_astcfgint(myrpt
, mcat
, "idfrequency", 300, 3000, 330);
2734 /* Is it a file, or a tone sequence? */
2736 if(entry
[0] == '|'){
2738 if((c
>= 'a')&&(c
<= 'z'))
2742 case 'I': /* Morse ID */
2743 res
= send_morse(chan
, entry
+ 2, morsespeed
, morseidfreq
, morseidampl
);
2746 case 'M': /* Morse Message */
2747 res
= send_morse(chan
, entry
+ 2, morsespeed
, morsefreq
, morseampl
);
2750 case 'T': /* Tone sequence */
2751 res
= send_tone_telemetry(chan
, entry
+ 2);
2758 res
= sayfile(chan
, entry
); /* File */
2763 * This function looks up a telemetry name in the config file, and does a telemetry response as configured.
2765 * 4 types of telemtry are handled: Morse ID, Morse Message, Tone Sequence, and a File containing a recording.
2768 static int telem_lookup(struct rpt
*myrpt
,struct ast_channel
*chan
, char *node
, char *name
)
2775 char *telemetry_save
;
2778 telemetry_save
= NULL
;
2781 /* Retrieve the section name for telemetry from the node section */
2782 telemetry
= (char *) ast_variable_retrieve(myrpt
->cfg
, node
, TELEMETRY
);
2784 telemetry_save
= ast_strdupa(telemetry
);
2785 if(!telemetry_save
){
2786 ast_log(LOG_WARNING
,"ast_strdupa() failed in telem_lookup()\n");
2789 entry
= (char *) ast_variable_retrieve(myrpt
->cfg
, telemetry_save
, name
);
2792 /* Try to look up the telemetry name */
2795 /* Telemetry name wasn't found in the config file, use the default */
2796 for(i
= 0; i
< sizeof(tele_defs
)/sizeof(struct telem_defaults
) ; i
++){
2797 if(!strcasecmp(tele_defs
[i
].name
, name
))
2798 entry
= tele_defs
[i
].value
;
2803 telem_any(myrpt
,chan
, entry
);
2812 * Retrieve a wait interval
2815 static int get_wait_interval(struct rpt
*myrpt
, int type
)
2819 char *wait_times_save
;
2821 wait_times_save
= NULL
;
2822 wait_times
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->name
, "wait_times");
2825 wait_times_save
= ast_strdupa(wait_times
);
2826 if(!wait_times_save
){
2827 ast_log(LOG_WARNING
, "Out of memory in wait_interval()\n");
2835 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "telemwait", 500, 5000, 1000);
2842 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "idwait",250,5000,500);
2849 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "unkeywait",500,5000,1000);
2856 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "linkunkeywait",500,5000,1000);
2863 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "calltermwait",500,5000,1500);
2870 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "compwait",500,5000,200);
2883 * Wait a configurable interval of time
2887 static void wait_interval(struct rpt
*myrpt
, int type
, struct ast_channel
*chan
)
2890 interval
= get_wait_interval(myrpt
, type
);
2892 ast_log(LOG_NOTICE
," Delay interval = %d\n", interval
);
2894 ast_safe_sleep(chan
,interval
);
2896 ast_log(LOG_NOTICE
,"Delay complete\n");
2900 static int split_freq(char *mhz
, char *decimals
, char *freq
);
2902 static void *rpt_tele_thread(void *this)
2904 struct dahdi_confinfo ci
; /* conference info */
2905 int res
= 0,haslink
,hastx
,hasremote
,imdone
= 0, unkeys_queued
, x
;
2906 struct rpt_tele
*mytele
= (struct rpt_tele
*)this;
2907 struct rpt_tele
*tlist
;
2909 struct rpt_link
*l
,*l1
,linkbase
;
2910 struct ast_channel
*mychannel
;
2911 int vmajor
, vminor
, m
;
2912 char *p
,*ct
,*ct_copy
,*ident
, *nodename
,*cp
;
2915 char lbuf
[MAXLINKLIST
],*strs
[MAXLINKLIST
];
2917 char mhz
[MAXREMSTR
];
2918 char decimals
[MAXREMSTR
];
2919 struct dahdi_params par
;
2922 /* get a pointer to myrpt */
2923 myrpt
= mytele
->rpt
;
2925 /* Snag copies of a few key myrpt variables */
2926 rpt_mutex_lock(&myrpt
->lock
);
2927 nodename
= ast_strdupa(myrpt
->name
);
2928 if (myrpt
->p
.ident
) ident
= ast_strdupa(myrpt
->p
.ident
);
2930 rpt_mutex_unlock(&myrpt
->lock
);
2932 /* allocate a pseudo-channel thru asterisk */
2933 mychannel
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
2936 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
2937 rpt_mutex_lock(&myrpt
->lock
);
2938 remque((struct qelem
*)mytele
);
2939 ast_log(LOG_NOTICE
,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__
, mytele
->mode
); /*@@@@@@@@@@@*/
2940 rpt_mutex_unlock(&myrpt
->lock
);
2944 #ifdef AST_CDR_FLAG_POST_DISABLED
2945 ast_set_flag(mychannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
2947 rpt_mutex_lock(&myrpt
->lock
);
2948 mytele
->chan
= mychannel
;
2949 rpt_mutex_unlock(&myrpt
->lock
);
2950 /* make a conference for the tx */
2952 /* If there's an ID queued, or tail message queued, */
2953 /* only connect the ID audio to the local tx conference so */
2954 /* linked systems can't hear it */
2955 ci
.confno
= (((mytele
->mode
== ID
) || (mytele
->mode
== IDTALKOVER
) || (mytele
->mode
== UNKEY
) ||
2956 (mytele
->mode
== TAILMSG
) || (mytele
->mode
== LINKUNKEY
)) || (mytele
->mode
== TIMEOUT
) ?
2957 myrpt
->txconf
: myrpt
->conf
);
2958 ci
.confmode
= DAHDI_CONF_CONFANN
;
2959 /* first put the channel on the conference in announce mode */
2960 if (ioctl(mychannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
2962 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
2963 rpt_mutex_lock(&myrpt
->lock
);
2964 remque((struct qelem
*)mytele
);
2965 rpt_mutex_unlock(&myrpt
->lock
);
2966 ast_log(LOG_NOTICE
,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__
, mytele
->mode
); /*@@@@@@@@@@@*/
2968 ast_hangup(mychannel
);
2971 ast_stopstream(mychannel
);
2972 switch(mytele
->mode
)
2977 wait_interval(myrpt
, (mytele
->mode
== ID
) ? DLY_ID
: DLY_TELEM
,mychannel
);
2978 res
= telem_any(myrpt
,mychannel
, ident
);
2983 res
= ast_streamfile(mychannel
, myrpt
->p
.tailmessages
[myrpt
->tailmessagen
], mychannel
->language
);
2987 p
= (char *) ast_variable_retrieve(myrpt
->cfg
, nodename
, "idtalkover");
2989 res
= telem_any(myrpt
,mychannel
, p
);
2994 /* wait a little bit longer */
2995 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
2996 res
= telem_lookup(myrpt
, mychannel
, myrpt
->name
, "patchup");
2997 if(res
< 0){ /* Then default message */
2998 res
= ast_streamfile(mychannel
, "rpt/callproceeding", mychannel
->language
);
3002 /* wait a little bit longer */
3003 wait_interval(myrpt
, DLY_CALLTERM
, mychannel
);
3004 res
= telem_lookup(myrpt
, mychannel
, myrpt
->name
, "patchdown");
3005 if(res
< 0){ /* Then default message */
3006 res
= ast_streamfile(mychannel
, "rpt/callterminated", mychannel
->language
);
3010 /* wait a little bit */
3011 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3012 res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "functcomplete");
3014 case MACRO_NOTFOUND
:
3015 /* wait a little bit */
3016 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3017 res
= ast_streamfile(mychannel
, "rpt/macro_notfound", mychannel
->language
);
3020 /* wait a little bit */
3021 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3022 res
= ast_streamfile(mychannel
, "rpt/macro_busy", mychannel
->language
);
3025 if(myrpt
->patchnoct
&& myrpt
->callmode
){ /* If no CT during patch configured, then don't send one */
3031 * Reset the Unkey to CT timer
3034 x
= get_wait_interval(myrpt
, DLY_UNKEY
);
3035 rpt_mutex_lock(&myrpt
->lock
);
3036 myrpt
->unkeytocttimer
= x
; /* Must be protected as it is changed below */
3037 rpt_mutex_unlock(&myrpt
->lock
);
3040 * If there's one already queued, don't do another
3043 tlist
= myrpt
->tele
.next
;
3045 if (tlist
!= &myrpt
->tele
)
3047 rpt_mutex_lock(&myrpt
->lock
);
3048 while(tlist
!= &myrpt
->tele
){
3049 if (tlist
->mode
== UNKEY
) unkeys_queued
++;
3050 tlist
= tlist
->next
;
3052 rpt_mutex_unlock(&myrpt
->lock
);
3054 if( unkeys_queued
> 1){
3059 /* Wait for the telemetry timer to expire */
3060 /* Periodically check the timer since it can be re-initialized above */
3061 while(myrpt
->unkeytocttimer
)
3064 if(myrpt
->unkeytocttimer
> 100)
3067 ctint
= myrpt
->unkeytocttimer
;
3068 ast_safe_sleep(mychannel
, ctint
);
3069 rpt_mutex_lock(&myrpt
->lock
);
3070 if(myrpt
->unkeytocttimer
< ctint
)
3071 myrpt
->unkeytocttimer
= 0;
3073 myrpt
->unkeytocttimer
-= ctint
;
3074 rpt_mutex_unlock(&myrpt
->lock
);
3078 * Now, the carrier on the rptr rx should be gone.
3079 * If it re-appeared, then forget about sending the CT
3086 rpt_mutex_lock(&myrpt
->lock
); /* Update the kerchunk counters */
3087 myrpt
->dailykerchunks
++;
3088 myrpt
->totalkerchunks
++;
3089 rpt_mutex_unlock(&myrpt
->lock
);
3094 l
= myrpt
->links
.next
;
3095 if (l
!= &myrpt
->links
)
3097 rpt_mutex_lock(&myrpt
->lock
);
3098 while(l
!= &myrpt
->links
)
3100 if (l
->name
[0] == '0')
3108 if (l
->isremote
) hasremote
++;
3112 rpt_mutex_unlock(&myrpt
->lock
);
3117 res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, (!hastx
) ? "remotemon" : "remotetx");
3119 ast_log(LOG_WARNING
, "telem_lookup:remotexx failed on %s\n", mychannel
->name
);
3122 /* if in remote cmd mode, indicate it */
3123 if (myrpt
->cmdnode
[0])
3125 ast_safe_sleep(mychannel
,200);
3126 res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "cmdmode");
3128 ast_log(LOG_WARNING
, "telem_lookup:cmdmode failed on %s\n", mychannel
->name
);
3129 ast_stopstream(mychannel
);
3132 else if((ct
= (char *) ast_variable_retrieve(myrpt
->cfg
, nodename
, "unlinkedct"))){ /* Unlinked Courtesy Tone */
3133 ct_copy
= ast_strdupa(ct
);
3134 res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, ct_copy
);
3136 ast_log(LOG_WARNING
, "telem_lookup:ctx failed on %s\n", mychannel
->name
);
3138 if (hasremote
&& (!myrpt
->cmdnode
[0]))
3140 /* set for all to hear */
3142 ci
.confno
= myrpt
->conf
;
3143 ci
.confmode
= DAHDI_CONF_CONFANN
;
3144 /* first put the channel on the conference in announce mode */
3145 if (ioctl(mychannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
3147 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
3148 rpt_mutex_lock(&myrpt
->lock
);
3149 remque((struct qelem
*)mytele
);
3150 rpt_mutex_unlock(&myrpt
->lock
);
3151 ast_log(LOG_NOTICE
,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__
, mytele
->mode
); /*@@@@@@@@@@@*/
3153 ast_hangup(mychannel
);
3156 if((ct
= (char *) ast_variable_retrieve(myrpt
->cfg
, nodename
, "remotect"))){ /* Unlinked Courtesy Tone */
3157 ast_safe_sleep(mychannel
,200);
3158 ct_copy
= ast_strdupa(ct
);
3159 res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, ct_copy
);
3161 ast_log(LOG_WARNING
, "telem_lookup:ctx failed on %s\n", mychannel
->name
);
3164 #if defined(_MDC_DECODE_H_) && defined(MDC_SAY_WHEN_DOING_CT)
3165 if (myrpt
->lastunit
)
3169 ast_safe_sleep(mychannel
,200);
3170 /* set for all to hear */
3172 ci
.confno
= myrpt
->txconf
;
3173 ci
.confmode
= DAHDI_CONF_CONFANN
;
3174 /* first put the channel on the conference in announce mode */
3175 if (ioctl(mychannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
3177 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
3178 rpt_mutex_lock(&myrpt
->lock
);
3179 remque((struct qelem
*)mytele
);
3180 rpt_mutex_unlock(&myrpt
->lock
);
3181 ast_log(LOG_NOTICE
,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__
, mytele
->mode
); /*@@@@@@@@@@@*/
3183 ast_hangup(mychannel
);
3186 sprintf(mystr
,"%04x",myrpt
->lastunit
);
3187 myrpt
->lastunit
= 0;
3188 ast_say_character_str(mychannel
,mystr
,NULL
,mychannel
->language
);
3195 if(myrpt
->patchnoct
&& myrpt
->callmode
){ /* If no CT during patch configured, then don't send one */
3201 * Reset the Unkey to CT timer
3204 x
= get_wait_interval(myrpt
, DLY_LINKUNKEY
);
3205 mytele
->mylink
.linkunkeytocttimer
= x
; /* Must be protected as it is changed below */
3208 * If there's one already queued, don't do another
3211 tlist
= myrpt
->tele
.next
;
3213 if (tlist
!= &myrpt
->tele
)
3215 rpt_mutex_lock(&myrpt
->lock
);
3216 while(tlist
!= &myrpt
->tele
){
3217 if (tlist
->mode
== LINKUNKEY
) unkeys_queued
++;
3218 tlist
= tlist
->next
;
3220 rpt_mutex_unlock(&myrpt
->lock
);
3222 if( unkeys_queued
> 1){
3227 /* Wait for the telemetry timer to expire */
3228 /* Periodically check the timer since it can be re-initialized above */
3229 while(mytele
->mylink
.linkunkeytocttimer
)
3232 if(mytele
->mylink
.linkunkeytocttimer
> 100)
3235 ctint
= mytele
->mylink
.linkunkeytocttimer
;
3236 ast_safe_sleep(mychannel
, ctint
);
3237 rpt_mutex_lock(&myrpt
->lock
);
3238 if(mytele
->mylink
.linkunkeytocttimer
< ctint
)
3239 mytele
->mylink
.linkunkeytocttimer
= 0;
3241 mytele
->mylink
.linkunkeytocttimer
-= ctint
;
3242 rpt_mutex_unlock(&myrpt
->lock
);
3245 if((ct
= (char *) ast_variable_retrieve(myrpt
->cfg
, nodename
, "linkunkeyct"))){ /* Unlinked Courtesy Tone */
3246 ct_copy
= ast_strdupa(ct
);
3247 res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, ct_copy
);
3249 ast_log(LOG_WARNING
, "telem_lookup:ctx failed on %s\n", mychannel
->name
);
3254 /* wait a little bit */
3255 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3256 l
= myrpt
->links
.next
;
3258 /* dont report if a link for this one still on system */
3259 if (l
!= &myrpt
->links
)
3261 rpt_mutex_lock(&myrpt
->lock
);
3262 while(l
!= &myrpt
->links
)
3264 if (l
->name
[0] == '0')
3269 if (!strcmp(l
->name
,mytele
->mylink
.name
))
3276 rpt_mutex_unlock(&myrpt
->lock
);
3283 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3285 res
= ast_waitstream(mychannel
, "");
3287 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3288 ast_stopstream(mychannel
);
3289 ast_say_character_str(mychannel
,mytele
->mylink
.name
,NULL
,mychannel
->language
);
3290 res
= ast_streamfile(mychannel
, ((mytele
->mylink
.hasconnected
) ?
3291 "rpt/remote_disc" : "rpt/remote_busy"), mychannel
->language
);
3294 /* wait a little bit */
3295 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3296 res
= ast_streamfile(mychannel
, "rpt/remote_already", mychannel
->language
);
3299 /* wait a little bit */
3300 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3301 res
= ast_streamfile(mychannel
, "rpt/remote_notfound", mychannel
->language
);
3304 /* wait a little bit */
3305 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3306 res
= ast_streamfile(mychannel
, "rpt/remote_go", mychannel
->language
);
3309 /* wait a little bit */
3310 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3311 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3313 res
= ast_waitstream(mychannel
, "");
3315 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3316 ast_stopstream(mychannel
);
3317 ast_say_character_str(mychannel
,mytele
->mylink
.name
,NULL
,mychannel
->language
);
3318 res
= ast_streamfile(mychannel
, "rpt/connected", mychannel
->language
);
3320 res
= ast_waitstream(mychannel
, "");
3322 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3323 ast_stopstream(mychannel
);
3324 res
= ast_streamfile(mychannel
, "digits/2", mychannel
->language
);
3326 res
= ast_waitstream(mychannel
, "");
3328 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3329 ast_stopstream(mychannel
);
3330 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3332 res
= ast_waitstream(mychannel
, "");
3334 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3335 ast_stopstream(mychannel
);
3336 ast_say_character_str(mychannel
,myrpt
->name
,NULL
,mychannel
->language
);
3340 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3342 res
= ast_waitstream(mychannel
, "");
3344 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3345 ast_stopstream(mychannel
);
3346 ast_say_character_str(mychannel
,mytele
->mylink
.name
,NULL
,mychannel
->language
);
3347 res
= ast_streamfile(mychannel
, "rpt/connection_failed", mychannel
->language
);
3350 /* wait a little bit */
3351 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3352 res
= ast_streamfile(mychannel
, "rpt/memory_notfound", mychannel
->language
);
3355 ast_mutex_lock(&myrpt
->remlock
);
3357 if(!strcmp(myrpt
->remote
, remote_rig_ft897
))
3359 res
= set_ft897(myrpt
);
3361 if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
3363 res
= set_ic706(myrpt
);
3365 else if(!strcmp(myrpt
->remote
, remote_rig_rbi
))
3367 if (ioperm(myrpt
->p
.iobase
,1,1) == -1)
3369 rpt_mutex_unlock(&myrpt
->lock
);
3370 ast_log(LOG_WARNING
, "Cant get io permission on IO port %x hex\n",myrpt
->p
.iobase
);
3373 else res
= setrbi(myrpt
);
3375 else if(!strcmp(myrpt
->remote
, remote_rig_kenwood
))
3377 res
= setkenwood(myrpt
);
3378 if (ast_safe_sleep(mychannel
,200) == -1)
3380 ast_mutex_unlock(&myrpt
->remlock
);
3384 i
= DAHDI_FLUSH_EVENT
;
3385 if (ioctl(myrpt
->zaptxchannel
->fds
[0],DAHDI_FLUSH
,&i
) == -1)
3387 ast_mutex_unlock(&myrpt
->remlock
);
3388 ast_log(LOG_ERROR
,"Cant flush events");
3392 if (ioctl(myrpt
->zaprxchannel
->fds
[0],DAHDI_GET_PARAMS
,&par
) == -1)
3394 ast_mutex_unlock(&myrpt
->remlock
);
3395 ast_log(LOG_ERROR
,"Cant get params");
3400 (par
.rxisoffhook
|| (myrpt
->tele
.next
!= &myrpt
->tele
));
3402 ast_mutex_unlock(&myrpt
->remlock
);
3408 /* fall thru to invalid freq */
3410 /* wait a little bit */
3411 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3412 res
= ast_streamfile(mychannel
, "rpt/invalid-freq", mychannel
->language
);
3416 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3417 switch(myrpt
->remmode
)
3420 saycharstr(mychannel
,"FM");
3423 saycharstr(mychannel
,"USB");
3426 saycharstr(mychannel
,"LSB");
3429 saycharstr(mychannel
,"AM");
3432 wait_interval(myrpt
, DLY_COMP
, mychannel
);
3433 if (!res
) res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "functcomplete");
3436 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3437 sayfile(mychannel
,"rpt/login");
3438 saycharstr(mychannel
,myrpt
->name
);
3441 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3442 saycharstr(mychannel
,myrpt
->loginuser
);
3443 sayfile(mychannel
,"rpt/node");
3444 saycharstr(mychannel
,myrpt
->name
);
3445 wait_interval(myrpt
, DLY_COMP
, mychannel
);
3446 if (!res
) res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "functcomplete");
3449 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3451 switch(mytele
->submode
)
3453 case 100: /* RX PL Off */
3454 sayfile(mychannel
, "rpt/rxpl");
3455 sayfile(mychannel
, "rpt/off");
3457 case 101: /* RX PL On */
3458 sayfile(mychannel
, "rpt/rxpl");
3459 sayfile(mychannel
, "rpt/on");
3461 case 102: /* TX PL Off */
3462 sayfile(mychannel
, "rpt/txpl");
3463 sayfile(mychannel
, "rpt/off");
3465 case 103: /* TX PL On */
3466 sayfile(mychannel
, "rpt/txpl");
3467 sayfile(mychannel
, "rpt/on");
3469 case 104: /* Low Power */
3470 sayfile(mychannel
, "rpt/lopwr");
3472 case 105: /* Medium Power */
3473 sayfile(mychannel
, "rpt/medpwr");
3475 case 106: /* Hi Power */
3476 sayfile(mychannel
, "rpt/hipwr");
3478 case 113: /* Scan down slow */
3479 sayfile(mychannel
,"rpt/down");
3480 sayfile(mychannel
, "rpt/slow");
3482 case 114: /* Scan down quick */
3483 sayfile(mychannel
,"rpt/down");
3484 sayfile(mychannel
, "rpt/quick");
3486 case 115: /* Scan down fast */
3487 sayfile(mychannel
,"rpt/down");
3488 sayfile(mychannel
, "rpt/fast");
3490 case 116: /* Scan up slow */
3491 sayfile(mychannel
,"rpt/up");
3492 sayfile(mychannel
, "rpt/slow");
3494 case 117: /* Scan up quick */
3495 sayfile(mychannel
,"rpt/up");
3496 sayfile(mychannel
, "rpt/quick");
3498 case 118: /* Scan up fast */
3499 sayfile(mychannel
,"rpt/up");
3500 sayfile(mychannel
, "rpt/fast");
3505 wait_interval(myrpt
, DLY_COMP
, mychannel
);
3506 if (!res
) res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "functcomplete");
3509 ast_mutex_lock(&myrpt
->remlock
);
3510 if (myrpt
->hfscanstop
)
3512 myrpt
->hfscanstatus
= 0;
3513 myrpt
->hfscanmode
= 0;
3514 myrpt
->hfscanstop
= 0;
3515 mytele
->mode
= SCANSTAT
;
3516 ast_mutex_unlock(&myrpt
->remlock
);
3517 if (ast_safe_sleep(mychannel
,1000) == -1) break;
3518 sayfile(mychannel
, "rpt/stop");
3522 if (myrpt
->hfscanstatus
> -2) service_scan(myrpt
);
3523 i
= myrpt
->hfscanstatus
;
3524 myrpt
->hfscanstatus
= 0;
3525 if (i
) mytele
->mode
= SCANSTAT
;
3526 ast_mutex_unlock(&myrpt
->remlock
);
3527 if (i
< 0) sayfile(mychannel
, "rpt/stop");
3528 else if (i
> 0) saynum(mychannel
,i
);
3532 ast_mutex_lock(&myrpt
->remlock
);
3533 if (!strcmp(myrpt
->remote
,remote_rig_ic706
))
3535 set_mode_ic706(myrpt
, REM_MODE_AM
);
3536 if(play_tone(mychannel
, 800, 6000, 8192) == -1) break;
3537 ast_safe_sleep(mychannel
,500);
3538 set_mode_ic706(myrpt
, myrpt
->remmode
);
3539 myrpt
->tunerequest
= 0;
3540 ast_mutex_unlock(&myrpt
->remlock
);
3544 set_mode_ft897(myrpt
, REM_MODE_AM
);
3545 simple_command_ft897(myrpt
, 8);
3546 if(play_tone(mychannel
, 800, 6000, 8192) == -1) break;
3547 simple_command_ft897(myrpt
, 0x88);
3548 ast_safe_sleep(mychannel
,500);
3549 set_mode_ft897(myrpt
, myrpt
->remmode
);
3550 myrpt
->tunerequest
= 0;
3551 ast_mutex_unlock(&myrpt
->remlock
);
3554 case REMSHORTSTATUS
:
3556 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3557 res
= sayfile(mychannel
,"rpt/node");
3559 res
= saycharstr(mychannel
, myrpt
->name
);
3561 res
= sayfile(mychannel
,"rpt/frequency");
3563 res
= split_freq(mhz
, decimals
, myrpt
->freq
);
3564 if (!multimode_capable(myrpt
)) decimals
[3] = 0;
3568 res
= saynum(mychannel
, m
);
3570 res
= saycharstr(mychannel
, mhz
);
3573 res
= sayfile(mychannel
, "letters/dot");
3575 res
= saycharstr(mychannel
, decimals
);
3578 if(myrpt
->remmode
== REM_MODE_FM
){ /* Mode FM? */
3579 switch(myrpt
->offset
){
3582 res
= sayfile(mychannel
,"rpt/minus");
3586 res
= sayfile(mychannel
,"rpt/simplex");
3590 res
= sayfile(mychannel
,"rpt/plus");
3597 else{ /* Must be USB, LSB, or AM */
3598 switch(myrpt
->remmode
){
3601 res
= saycharstr(mychannel
, "USB");
3605 res
= saycharstr(mychannel
, "LSB");
3609 res
= saycharstr(mychannel
, "AM");
3618 if (res
== -1) break;
3620 if(mytele
->mode
== REMSHORTSTATUS
){ /* Short status? */
3621 wait_interval(myrpt
, DLY_COMP
, mychannel
);
3622 if (!res
) res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "functcomplete");
3626 if (strcmp(myrpt
->remote
,remote_rig_ic706
))
3628 switch(myrpt
->powerlevel
){
3631 res
= sayfile(mychannel
,"rpt/lopwr") ;
3634 res
= sayfile(mychannel
,"rpt/medpwr");
3637 res
= sayfile(mychannel
,"rpt/hipwr");
3642 rbimode
= ((!strncmp(myrpt
->remote
,remote_rig_rbi
,3))
3643 || (!strncmp(myrpt
->remote
,remote_rig_ic706
,3)));
3644 if (res
|| (sayfile(mychannel
,"rpt/rxpl") == -1)) break;
3645 if (rbimode
&& (sayfile(mychannel
,"rpt/txpl") == -1)) break;
3646 if ((sayfile(mychannel
,"rpt/frequency") == -1) ||
3647 (saycharstr(mychannel
,myrpt
->rxpl
) == -1)) break;
3648 if ((!rbimode
) && ((sayfile(mychannel
,"rpt/txpl") == -1) ||
3649 (sayfile(mychannel
,"rpt/frequency") == -1) ||
3650 (saycharstr(mychannel
,myrpt
->txpl
) == -1))) break;
3651 if(myrpt
->remmode
== REM_MODE_FM
){ /* Mode FM? */
3652 if ((sayfile(mychannel
,"rpt/rxpl") == -1) ||
3653 (sayfile(mychannel
,((myrpt
->rxplon
) ? "rpt/on" : "rpt/off")) == -1) ||
3654 (sayfile(mychannel
,"rpt/txpl") == -1) ||
3655 (sayfile(mychannel
,((myrpt
->txplon
) ? "rpt/on" : "rpt/off")) == -1))
3660 wait_interval(myrpt
, DLY_COMP
, mychannel
);
3661 if (!res
) res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "functcomplete");
3664 /* wait a little bit */
3665 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3667 linkbase
.next
= &linkbase
;
3668 linkbase
.prev
= &linkbase
;
3669 rpt_mutex_lock(&myrpt
->lock
);
3670 /* make our own list of links */
3671 l
= myrpt
->links
.next
;
3672 while(l
!= &myrpt
->links
)
3674 if (l
->name
[0] == '0')
3679 l1
= malloc(sizeof(struct rpt_link
));
3682 ast_log(LOG_WARNING
, "Cannot alloc memory on %s\n", mychannel
->name
);
3683 remque((struct qelem
*)mytele
);
3684 rpt_mutex_unlock(&myrpt
->lock
);
3685 ast_log(LOG_NOTICE
,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__
, mytele
->mode
); /*@@@@@@@@@@@*/
3687 ast_hangup(mychannel
);
3690 memcpy(l1
,l
,sizeof(struct rpt_link
));
3691 l1
->next
= l1
->prev
= NULL
;
3692 insque((struct qelem
*)l1
,(struct qelem
*)linkbase
.next
);
3695 rpt_mutex_unlock(&myrpt
->lock
);
3696 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3698 res
= ast_waitstream(mychannel
, "");
3700 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3701 ast_stopstream(mychannel
);
3702 ast_say_character_str(mychannel
,myrpt
->name
,NULL
,mychannel
->language
);
3704 res
= ast_waitstream(mychannel
, "");
3706 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3707 ast_stopstream(mychannel
);
3708 if (myrpt
->callmode
)
3711 res
= ast_streamfile(mychannel
, "rpt/autopatch_on", mychannel
->language
);
3713 res
= ast_waitstream(mychannel
, "");
3715 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3716 ast_stopstream(mychannel
);
3719 while(l
!= &linkbase
)
3724 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3726 res
= ast_waitstream(mychannel
, "");
3728 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3729 ast_stopstream(mychannel
);
3730 ast_say_character_str(mychannel
,l
->name
,NULL
,mychannel
->language
);
3732 res
= ast_waitstream(mychannel
, "");
3734 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3735 ast_stopstream(mychannel
);
3736 s
= "rpt/tranceive";
3737 if (!l
->mode
) s
= "rpt/monitor";
3738 if (!l
->thisconnected
) s
= "rpt/connecting";
3739 res
= ast_streamfile(mychannel
, s
, mychannel
->language
);
3741 res
= ast_waitstream(mychannel
, "");
3743 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3744 ast_stopstream(mychannel
);
3749 res
= ast_streamfile(mychannel
, "rpt/repeat_only", mychannel
->language
);
3751 res
= ast_waitstream(mychannel
, "");
3753 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3754 ast_stopstream(mychannel
);
3756 /* destroy our local link queue */
3758 while(l
!= &linkbase
)
3762 remque((struct qelem
*)l1
);
3768 rpt_mutex_lock(&myrpt
->lock
);
3769 /* get all the nodes */
3770 __mklinklist(myrpt
,NULL
,lbuf
);
3771 rpt_mutex_unlock(&myrpt
->lock
);
3773 ns
= finddelim(lbuf
,strs
,MAXLINKLIST
);
3775 if (ns
) qsort((void *)strs
,ns
,sizeof(char *),mycompar
);
3776 /* wait a little bit */
3777 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3779 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3781 res
= ast_waitstream(mychannel
, "");
3783 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3784 ast_stopstream(mychannel
);
3785 ast_say_character_str(mychannel
,myrpt
->name
,NULL
,mychannel
->language
);
3787 res
= ast_waitstream(mychannel
, "");
3789 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3790 ast_stopstream(mychannel
);
3791 if (myrpt
->callmode
)
3794 res
= ast_streamfile(mychannel
, "rpt/autopatch_on", mychannel
->language
);
3796 res
= ast_waitstream(mychannel
, "");
3798 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3799 ast_stopstream(mychannel
);
3801 /* go thru all the nodes in list */
3802 for(i
= 0; i
< ns
; i
++)
3806 /* if a mode spec at first, handle it */
3807 if ((*strs
[i
] < '0') || (*strs
[i
] > '9'))
3814 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3816 res
= ast_waitstream(mychannel
, "");
3818 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3819 ast_stopstream(mychannel
);
3820 ast_say_character_str(mychannel
,strs
[i
],NULL
,mychannel
->language
);
3822 res
= ast_waitstream(mychannel
, "");
3824 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3825 ast_stopstream(mychannel
);
3826 s
= "rpt/tranceive";
3827 if (mode
== 'R') s
= "rpt/monitor";
3828 if (mode
== 'C') s
= "rpt/connecting";
3829 res
= ast_streamfile(mychannel
, s
, mychannel
->language
);
3831 res
= ast_waitstream(mychannel
, "");
3833 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3834 ast_stopstream(mychannel
);
3838 res
= ast_streamfile(mychannel
, "rpt/repeat_only", mychannel
->language
);
3840 res
= ast_waitstream(mychannel
, "");
3842 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3843 ast_stopstream(mychannel
);
3848 case LASTNODEKEY
: /* Identify last node which keyed us up */
3849 rpt_mutex_lock(&myrpt
->lock
);
3850 if(myrpt
->lastnodewhichkeyedusup
)
3851 p
= ast_strdupa(myrpt
->lastnodewhichkeyedusup
); /* Make a local copy of the node name */
3854 rpt_mutex_unlock(&myrpt
->lock
);
3856 imdone
= 1; /* no node previously keyed us up, or the node which did has been disconnected */
3859 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3860 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3862 res
= ast_waitstream(mychannel
, "");
3864 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3865 ast_stopstream(mychannel
);
3866 ast_say_character_str(mychannel
, p
, NULL
, mychannel
->language
);
3868 res
= ast_waitstream(mychannel
, "");
3870 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3871 ast_stopstream(mychannel
);
3875 case UNAUTHTX
: /* Say unauthorized transmit frequency */
3876 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
3877 res
= ast_streamfile(mychannel
, "rpt/unauthtx", mychannel
->language
);
3879 res
= ast_waitstream(mychannel
, "");
3881 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3882 ast_stopstream(mychannel
);
3888 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3890 res
= ast_waitstream(mychannel
, "");
3892 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3893 ast_stopstream(mychannel
);
3894 ast_say_character_str(mychannel
,myrpt
->name
,NULL
,mychannel
->language
);
3895 res
= ast_streamfile(mychannel
, "rpt/timeout", mychannel
->language
);
3898 case TIMEOUT_WARNING
:
3900 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3902 res
= ast_waitstream(mychannel
, "");
3904 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3905 ast_stopstream(mychannel
);
3906 ast_say_character_str(mychannel
,myrpt
->name
,NULL
,mychannel
->language
);
3907 res
= ast_streamfile(mychannel
, "rpt/timeout-warning", mychannel
->language
);
3909 res
= ast_waitstream(mychannel
, "");
3911 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3912 ast_stopstream(mychannel
);
3913 if(!res
) /* Say number of seconds */
3914 ast_say_number(mychannel
, myrpt
->p
.remotetimeout
-
3915 (t
- myrpt
->last_activity_time
),
3916 "", mychannel
->language
, (char *) NULL
);
3918 res
= ast_waitstream(mychannel
, "");
3919 ast_stopstream(mychannel
);
3920 res
= ast_streamfile(mychannel
, "queue-seconds", mychannel
->language
);
3923 case ACT_TIMEOUT_WARNING
:
3925 res
= ast_streamfile(mychannel
, "rpt/node", mychannel
->language
);
3927 res
= ast_waitstream(mychannel
, "");
3929 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3930 ast_stopstream(mychannel
);
3931 ast_say_character_str(mychannel
,myrpt
->name
,NULL
,mychannel
->language
);
3932 res
= ast_streamfile(mychannel
, "rpt/act-timeout-warning", mychannel
->language
);
3934 res
= ast_waitstream(mychannel
, "");
3936 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3937 ast_stopstream(mychannel
);
3938 if(!res
) /* Say number of seconds */
3939 ast_say_number(mychannel
, myrpt
->p
.remoteinacttimeout
-
3940 (t
- myrpt
->last_activity_time
),
3941 "", mychannel
->language
, (char *) NULL
);
3943 res
= ast_waitstream(mychannel
, "");
3944 ast_stopstream(mychannel
);
3945 res
= ast_streamfile(mychannel
, "queue-seconds", mychannel
->language
);
3949 wait_interval(myrpt
, DLY_TELEM
, mychannel
); /* Wait a little bit */
3951 rpt_localtime(&t
, &localtm
);
3952 /* Say the phase of the day is before the time */
3953 if((localtm
.tm_hour
>= 0) && (localtm
.tm_hour
< 12))
3954 p
= "rpt/goodmorning";
3955 else if((localtm
.tm_hour
>= 12) && (localtm
.tm_hour
< 18))
3956 p
= "rpt/goodafternoon";
3958 p
= "rpt/goodevening";
3959 if (sayfile(mychannel
,p
) == -1)
3964 /* Say the time is ... */
3965 if (sayfile(mychannel
,"rpt/thetimeis") == -1)
3971 res
= ast_say_time(mychannel
, t
, "", mychannel
->language
);
3973 res
= ast_waitstream(mychannel
, "");
3974 ast_stopstream(mychannel
);
3978 p
= strstr(tdesc
, "version");
3981 if(sscanf(p
, "version %d.%d", &vmajor
, &vminor
) != 2)
3983 wait_interval(myrpt
, DLY_TELEM
, mychannel
); /* Wait a little bit */
3985 if (sayfile(mychannel
,"rpt/version") == -1)
3990 if(!res
) /* Say "X" */
3991 ast_say_number(mychannel
, vmajor
, "", mychannel
->language
, (char *) NULL
);
3993 res
= ast_waitstream(mychannel
, "");
3994 ast_stopstream(mychannel
);
3995 if (saycharstr(mychannel
,".") == -1)
4000 if(!res
) /* Say "Y" */
4001 ast_say_number(mychannel
, vminor
, "", mychannel
->language
, (char *) NULL
);
4003 res
= ast_waitstream(mychannel
, "");
4004 ast_stopstream(mychannel
);
4007 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
4011 wait_interval(myrpt
, DLY_TELEM
, mychannel
); /* Wait a little bit */
4013 saycharstr(mychannel
, mytele
->param
);
4017 wait_interval(myrpt
, DLY_TELEM
, mychannel
); /* Wait a little bit */
4020 /* Parts of this section taken from app_parkandannounce */
4021 char *tpl_working
, *tpl_current
;
4022 char *tmp
[100], *myparm
;
4023 int looptemp
=0,i
=0, dres
= 0;
4026 tpl_working
= strdupa(mytele
->param
);
4027 myparm
= strsep(&tpl_working
,",");
4028 tpl_current
=strsep(&tpl_working
, ":");
4030 while(tpl_current
&& looptemp
< sizeof(tmp
)) {
4031 tmp
[looptemp
]=tpl_current
;
4033 tpl_current
=strsep(&tpl_working
,":");
4036 for(i
=0; i
<looptemp
; i
++) {
4037 if(!strcmp(tmp
[i
], "PARKED")) {
4038 ast_say_digits(mychannel
, atoi(myparm
), "", mychannel
->language
);
4039 } else if(!strcmp(tmp
[i
], "NODE")) {
4040 ast_say_digits(mychannel
, atoi(myrpt
->name
), "", mychannel
->language
);
4042 dres
= ast_streamfile(mychannel
, tmp
[i
], mychannel
->language
);
4044 dres
= ast_waitstream(mychannel
, "");
4046 ast_log(LOG_WARNING
, "ast_streamfile of %s failed on %s\n", tmp
[i
], mychannel
->name
);
4056 if (myrpt
->stopgen
) break;
4057 myrpt
->stopgen
= -1;
4058 if ((res
= ast_tonepair_start(mychannel
, 1004.0, 0, 99999999, 7200.0)))
4063 while(mychannel
->generatordata
&& (myrpt
->stopgen
<= 0)) {
4064 if (ast_safe_sleep(mychannel
,1)) break;
4075 res
= ast_waitstream(mychannel
, "");
4077 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
4081 ast_stopstream(mychannel
);
4082 rpt_mutex_lock(&myrpt
->lock
);
4083 if (mytele
->mode
== TAILMSG
)
4087 myrpt
->tailmessagen
++;
4088 if(myrpt
->tailmessagen
>= myrpt
->p
.tailmessagemax
) myrpt
->tailmessagen
= 0;
4092 myrpt
->tmsgtimer
= myrpt
->p
.tailsquashedtime
;
4095 remque((struct qelem
*)mytele
);
4096 rpt_mutex_unlock(&myrpt
->lock
);
4098 ast_hangup(mychannel
);
4099 #ifdef APP_RPT_LOCK_DEBUG
4101 struct lockthread
*t
;
4104 ast_mutex_lock(&locklock
);
4105 t
= get_lockthread(pthread_self());
4106 if (t
) memset(t
,0,sizeof(struct lockthread
));
4107 ast_mutex_unlock(&locklock
);
4113 static void rpt_telemetry(struct rpt
*myrpt
,int mode
, void *data
)
4115 struct rpt_tele
*tele
;
4116 struct rpt_link
*mylink
= (struct rpt_link
*) data
;
4118 pthread_attr_t attr
;
4120 tele
= malloc(sizeof(struct rpt_tele
));
4123 ast_log(LOG_WARNING
, "Unable to allocate memory\n");
4128 memset((char *)tele
,0,sizeof(struct rpt_tele
));
4131 rpt_mutex_lock(&myrpt
->lock
);
4132 if((mode
== CONNFAIL
) || (mode
== REMDISC
) || (mode
== CONNECTED
) ||
4133 (mode
== LINKUNKEY
)){
4134 memset(&tele
->mylink
,0,sizeof(struct rpt_link
));
4136 memcpy(&tele
->mylink
,mylink
,sizeof(struct rpt_link
));
4139 else if ((mode
== ARB_ALPHA
) || (mode
== REV_PATCH
)) {
4140 strncpy(tele
->param
, (char *) data
, TELEPARAMSIZE
- 1);
4141 tele
->param
[TELEPARAMSIZE
- 1] = 0;
4143 if (mode
== REMXXX
) tele
->submode
= (int) data
;
4144 insque((struct qelem
*)tele
, (struct qelem
*)myrpt
->tele
.next
);
4145 rpt_mutex_unlock(&myrpt
->lock
);
4146 pthread_attr_init(&attr
);
4147 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
4148 res
= ast_pthread_create(&tele
->threadid
,&attr
,rpt_tele_thread
,(void *) tele
);
4150 rpt_mutex_lock(&myrpt
->lock
);
4151 remque((struct qlem
*) tele
); /* We don't like stuck transmitters, remove it from the queue */
4152 rpt_mutex_unlock(&myrpt
->lock
);
4153 ast_log(LOG_WARNING
, "Could not create telemetry thread: %s",strerror(res
));
4158 static void *rpt_call(void *this)
4160 struct dahdi_confinfo ci
; /* conference info */
4161 struct rpt
*myrpt
= (struct rpt
*)this;
4163 int stopped
,congstarted
,dialtimer
,lastcidx
,aborted
;
4164 struct ast_channel
*mychannel
,*genchannel
;
4168 /* allocate a pseudo-channel thru asterisk */
4169 mychannel
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
4172 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
4175 #ifdef AST_CDR_FLAG_POST_DISABLED
4176 ast_set_flag(mychannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
4179 ci
.confno
= myrpt
->conf
; /* use the pseudo conference */
4180 ci
.confmode
= DAHDI_CONF_REALANDPSEUDO
| DAHDI_CONF_TALKER
| DAHDI_CONF_LISTENER
4181 | DAHDI_CONF_PSEUDO_TALKER
| DAHDI_CONF_PSEUDO_LISTENER
;
4182 /* first put the channel on the conference */
4183 if (ioctl(mychannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
4185 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
4186 ast_hangup(mychannel
);
4187 myrpt
->callmode
= 0;
4190 /* allocate a pseudo-channel thru asterisk */
4191 genchannel
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
4194 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
4195 ast_hangup(mychannel
);
4198 #ifdef AST_CDR_FLAG_POST_DISABLED
4199 ast_set_flag(genchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
4202 ci
.confno
= myrpt
->conf
;
4203 ci
.confmode
= DAHDI_CONF_REALANDPSEUDO
| DAHDI_CONF_TALKER
| DAHDI_CONF_LISTENER
4204 | DAHDI_CONF_PSEUDO_TALKER
| DAHDI_CONF_PSEUDO_LISTENER
;
4205 /* first put the channel on the conference */
4206 if (ioctl(genchannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
4208 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
4209 ast_hangup(mychannel
);
4210 ast_hangup(genchannel
);
4211 myrpt
->callmode
= 0;
4214 if (myrpt
->p
.tonezone
&& (tone_zone_set_zone(mychannel
->fds
[0],myrpt
->p
.tonezone
) == -1))
4216 ast_log(LOG_WARNING
, "Unable to set tone zone %s\n",myrpt
->p
.tonezone
);
4217 ast_hangup(mychannel
);
4218 ast_hangup(genchannel
);
4219 myrpt
->callmode
= 0;
4222 if (myrpt
->p
.tonezone
&& (tone_zone_set_zone(genchannel
->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 /* start dialtone if patchquiet is 0. Special patch modes don't send dial tone */
4231 if ((!myrpt
->patchquiet
) && (tone_zone_play_tone(mychannel
->fds
[0],DAHDI_TONE_DIALTONE
) < 0))
4233 ast_log(LOG_WARNING
, "Cannot start dialtone\n");
4234 ast_hangup(mychannel
);
4235 ast_hangup(genchannel
);
4236 myrpt
->callmode
= 0;
4246 while ((myrpt
->callmode
== 1) || (myrpt
->callmode
== 4))
4249 if((myrpt
->patchdialtime
)&&(myrpt
->callmode
== 1)&&(myrpt
->cidx
!= lastcidx
)){
4251 lastcidx
= myrpt
->cidx
;
4254 if((myrpt
->patchdialtime
)&&(dialtimer
>= myrpt
->patchdialtime
)){
4255 rpt_mutex_lock(&myrpt
->lock
);
4257 myrpt
->callmode
= 0;
4258 rpt_mutex_unlock(&myrpt
->lock
);
4262 if ((!myrpt
->patchquiet
) && (!stopped
) && (myrpt
->callmode
== 1) && (myrpt
->cidx
> 0))
4265 /* stop dial tone */
4266 tone_zone_play_tone(mychannel
->fds
[0],-1);
4268 if (myrpt
->callmode
== 4)
4272 /* start congestion tone */
4273 tone_zone_play_tone(mychannel
->fds
[0],DAHDI_TONE_CONGESTION
);
4276 res
= ast_safe_sleep(mychannel
, MSWAIT
);
4279 ast_hangup(mychannel
);
4280 ast_hangup(genchannel
);
4281 rpt_mutex_lock(&myrpt
->lock
);
4282 myrpt
->callmode
= 0;
4283 rpt_mutex_unlock(&myrpt
->lock
);
4286 dialtimer
+= MSWAIT
;
4288 /* stop any tone generation */
4289 tone_zone_play_tone(mychannel
->fds
[0],-1);
4291 if (!myrpt
->callmode
)
4293 ast_hangup(mychannel
);
4294 ast_hangup(genchannel
);
4295 rpt_mutex_lock(&myrpt
->lock
);
4296 myrpt
->callmode
= 0;
4297 rpt_mutex_unlock(&myrpt
->lock
);
4298 if((!myrpt
->patchquiet
) && aborted
)
4299 rpt_telemetry(myrpt
, TERM
, NULL
);
4303 if (myrpt
->p
.ourcallerid
&& *myrpt
->p
.ourcallerid
){
4304 char *name
, *loc
, *instr
;
4305 instr
= strdup(myrpt
->p
.ourcallerid
);
4307 ast_callerid_parse(instr
, &name
, &loc
);
4309 if(mychannel
->cid
.cid_num
)
4310 free(mychannel
->cid
.cid_num
);
4311 mychannel
->cid
.cid_num
= strdup(loc
);
4314 if(mychannel
->cid
.cid_name
)
4315 free(mychannel
->cid
.cid_name
);
4316 mychannel
->cid
.cid_name
= strdup(name
);
4322 ast_copy_string(mychannel
->exten
, myrpt
->exten
, sizeof(mychannel
->exten
) - 1);
4323 ast_copy_string(mychannel
->context
, myrpt
->patchcontext
, sizeof(mychannel
->context
) - 1);
4325 if (myrpt
->p
.acctcode
)
4326 ast_cdr_setaccount(mychannel
,myrpt
->p
.acctcode
);
4327 mychannel
->priority
= 1;
4328 ast_channel_undefer_dtmf(mychannel
);
4329 if (ast_pbx_start(mychannel
) < 0)
4331 ast_log(LOG_WARNING
, "Unable to start PBX!!\n");
4332 ast_hangup(mychannel
);
4333 ast_hangup(genchannel
);
4334 rpt_mutex_lock(&myrpt
->lock
);
4335 myrpt
->callmode
= 0;
4336 rpt_mutex_unlock(&myrpt
->lock
);
4340 rpt_mutex_lock(&myrpt
->lock
);
4341 myrpt
->callmode
= 3;
4342 /* set appropriate conference for the pseudo */
4344 ci
.confno
= myrpt
->conf
;
4345 ci
.confmode
= (myrpt
->p
.duplex
== 2) ? DAHDI_CONF_CONFANNMON
:
4346 (DAHDI_CONF_CONF
| DAHDI_CONF_LISTENER
| DAHDI_CONF_TALKER
);
4347 /* first put the channel on the conference in announce mode */
4348 if (ioctl(myrpt
->pchannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
4350 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
4351 ast_hangup(mychannel
);
4352 ast_hangup(genchannel
);
4353 myrpt
->callmode
= 0;
4356 while(myrpt
->callmode
)
4358 if ((!mychannel
->pbx
) && (myrpt
->callmode
!= 4))
4360 if(myrpt
->patchfarenddisconnect
){ /* If patch is setup for far end disconnect */
4361 myrpt
->callmode
= 0;
4362 if(!myrpt
->patchquiet
){
4363 rpt_mutex_unlock(&myrpt
->lock
);
4364 rpt_telemetry(myrpt
, TERM
, NULL
);
4365 rpt_mutex_lock(&myrpt
->lock
);
4368 else{ /* Send congestion until patch is downed by command */
4369 myrpt
->callmode
= 4;
4370 rpt_mutex_unlock(&myrpt
->lock
);
4371 /* start congestion tone */
4372 tone_zone_play_tone(genchannel
->fds
[0],DAHDI_TONE_CONGESTION
);
4373 rpt_mutex_lock(&myrpt
->lock
);
4378 struct ast_frame wf
= {AST_FRAME_DTMF
, } ;
4379 wf
.subclass
= myrpt
->mydtmf
;
4380 rpt_mutex_unlock(&myrpt
->lock
);
4381 ast_queue_frame(mychannel
,&wf
);
4382 ast_senddigit(genchannel
,myrpt
->mydtmf
);
4383 rpt_mutex_lock(&myrpt
->lock
);
4386 rpt_mutex_unlock(&myrpt
->lock
);
4387 usleep(MSWAIT
* 1000);
4388 rpt_mutex_lock(&myrpt
->lock
);
4390 rpt_mutex_unlock(&myrpt
->lock
);
4391 tone_zone_play_tone(genchannel
->fds
[0],-1);
4392 if (mychannel
->pbx
) ast_softhangup(mychannel
,AST_SOFTHANGUP_DEV
);
4393 ast_hangup(genchannel
);
4394 rpt_mutex_lock(&myrpt
->lock
);
4395 myrpt
->callmode
= 0;
4396 rpt_mutex_unlock(&myrpt
->lock
);
4397 /* set appropriate conference for the pseudo */
4399 ci
.confno
= myrpt
->conf
;
4400 ci
.confmode
= ((myrpt
->p
.duplex
== 2) || (myrpt
->p
.duplex
== 4)) ? DAHDI_CONF_CONFANNMON
:
4401 (DAHDI_CONF_CONF
| DAHDI_CONF_LISTENER
| DAHDI_CONF_TALKER
);
4402 /* first put the channel on the conference in announce mode */
4403 if (ioctl(myrpt
->pchannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
4405 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
4410 static void send_link_dtmf(struct rpt
*myrpt
,char c
)
4413 struct ast_frame wf
;
4416 snprintf(str
, sizeof(str
), "D %s %s %d %c", myrpt
->cmdnode
, myrpt
->name
, ++(myrpt
->dtmfidx
), c
);
4417 wf
.frametype
= AST_FRAME_TEXT
;
4421 wf
.datalen
= strlen(str
) + 1;
4423 l
= myrpt
->links
.next
;
4424 /* first, see if our dude is there */
4425 while(l
!= &myrpt
->links
)
4427 if (l
->name
[0] == '0')
4432 /* if we found it, write it and were done */
4433 if (!strcmp(l
->name
,myrpt
->cmdnode
))
4436 if (l
->chan
) ast_write(l
->chan
,&wf
);
4441 l
= myrpt
->links
.next
;
4442 /* if not, give it to everyone */
4443 while(l
!= &myrpt
->links
)
4446 if (l
->chan
) ast_write(l
->chan
,&wf
);
4459 * 2: Already connected to this node
4462 static int connect_link(struct rpt
*myrpt
, char* node
, int mode
, int perma
)
4464 char *val
, *s
, *s1
, *s2
, *tele
;
4465 char lstr
[MAXLINKLIST
],*strs
[MAXLINKLIST
];
4466 char tmp
[300], deststr
[300] = "",modechange
= 0;
4470 struct dahdi_confinfo ci
; /* conference info */
4472 val
= node_lookup(myrpt
,node
);
4474 if(strlen(node
) >= myrpt
->longestnode
)
4475 return -1; /* No such node */
4476 return 1; /* No match yet */
4479 ast_log(LOG_NOTICE
,"Connect attempt to node %s\n", node
);
4480 ast_log(LOG_NOTICE
,"Mode: %s\n",(mode
)?"Transceive":"Monitor");
4481 ast_log(LOG_NOTICE
,"Connection type: %s\n",(perma
)?"Permalink":"Normal");
4484 strncpy(tmp
,val
,sizeof(tmp
) - 1);
4486 s1
= strsep(&s
,",");
4487 s2
= strsep(&s
,",");
4488 rpt_mutex_lock(&myrpt
->lock
);
4489 l
= myrpt
->links
.next
;
4490 /* try to find this one in queue */
4491 while(l
!= &myrpt
->links
){
4492 if (l
->name
[0] == '0')
4497 /* if found matching string */
4498 if (!strcmp(l
->name
, node
))
4503 if (l
!= &myrpt
->links
){
4504 /* if already in this mode, just ignore */
4505 if ((l
->mode
) || (!l
->chan
)) {
4506 rpt_mutex_unlock(&myrpt
->lock
);
4507 return 2; /* Already linked */
4509 reconnects
= l
->reconnects
;
4510 rpt_mutex_unlock(&myrpt
->lock
);
4511 if (l
->chan
) ast_softhangup(l
->chan
, AST_SOFTHANGUP_DEV
);
4512 l
->retries
= l
->max_retries
+ 1;
4517 __mklinklist(myrpt
,NULL
,lstr
);
4518 rpt_mutex_unlock(&myrpt
->lock
);
4519 n
= finddelim(lstr
,strs
,MAXLINKLIST
);
4520 for(i
= 0; i
< n
; i
++)
4522 if ((*strs
[i
] < '0') ||
4523 (*strs
[i
] > '9')) strs
[i
]++;
4524 if (!strcmp(strs
[i
],node
))
4526 return 2; /* Already linked */
4530 strncpy(myrpt
->lastlinknode
,node
,MAXNODESTR
- 1);
4531 /* establish call */
4532 l
= malloc(sizeof(struct rpt_link
));
4535 ast_log(LOG_WARNING
, "Unable to malloc\n");
4538 /* zero the silly thing */
4539 memset((char *)l
,0,sizeof(struct rpt_link
));
4542 l
->thisconnected
= 0;
4543 strncpy(l
->name
, node
, MAXNODESTR
- 1);
4544 l
->isremote
= (s
&& ast_true(s
));
4545 if (modechange
) l
->connected
= 1;
4546 l
->hasconnected
= l
->perma
= perma
;
4547 #ifdef ALLOW_LOCAL_CHANNELS
4548 if ((strncasecmp(s1
,"iax2/", 5) == 0) || (strncasecmp(s1
, "local/", 6) == 0))
4549 strncpy(deststr
, s1
, sizeof(deststr
));
4551 snprintf(deststr
, sizeof(deststr
), "IAX2/%s", s1
);
4553 snprintf(deststr
, sizeof(deststr
), "IAX2/%s", s1
);
4555 tele
= strchr(deststr
, '/');
4557 ast_log(LOG_WARNING
,"link3:Dial number (%s) must be in format tech/number\n",deststr
);
4562 l
->chan
= ast_request(deststr
, AST_FORMAT_SLINEAR
, tele
,NULL
);
4564 ast_set_read_format(l
->chan
, AST_FORMAT_SLINEAR
);
4565 ast_set_write_format(l
->chan
, AST_FORMAT_SLINEAR
);
4566 #ifdef AST_CDR_FLAG_POST_DISABLED
4567 ast_set_flag(l
->chan
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
4569 l
->chan
->whentohangup
= 0;
4570 l
->chan
->appl
= "Apprpt";
4571 l
->chan
->data
= "(Remote Rx)";
4573 ast_log(LOG_NOTICE
, "rpt (remote) initiating call to %s/%s on %s\n",
4574 deststr
, tele
, l
->chan
->name
);
4575 if(l
->chan
->cid
.cid_num
)
4576 free(l
->chan
->cid
.cid_num
);
4577 l
->chan
->cid
.cid_num
= strdup(myrpt
->name
);
4578 ast_call(l
->chan
,tele
,999);
4582 ast_log(LOG_NOTICE
, "Unable to place call to %s/%s on %s\n",
4583 deststr
,tele
,l
->chan
->name
);
4584 if (myrpt
->p
.archivedir
)
4587 sprintf(str
,"LINKFAIL,%s",l
->name
);
4588 donodelog(myrpt
,str
);
4593 /* allocate a pseudo-channel thru asterisk */
4594 l
->pchan
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
4596 ast_log(LOG_WARNING
,"rpt connect: Sorry unable to obtain pseudo channel\n");
4597 ast_hangup(l
->chan
);
4601 ast_set_read_format(l
->pchan
, AST_FORMAT_SLINEAR
);
4602 ast_set_write_format(l
->pchan
, AST_FORMAT_SLINEAR
);
4603 #ifdef AST_CDR_FLAG_POST_DISABLED
4604 ast_set_flag(l
->pchan
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
4606 /* make a conference for the tx */
4608 ci
.confno
= myrpt
->conf
;
4609 ci
.confmode
= DAHDI_CONF_CONF
| DAHDI_CONF_LISTENER
| DAHDI_CONF_TALKER
;
4610 /* first put the channel on the conference in proper mode */
4611 if (ioctl(l
->pchan
->fds
[0], DAHDI_SETCONF
, &ci
) == -1)
4613 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
4614 ast_hangup(l
->chan
);
4615 ast_hangup(l
->pchan
);
4619 rpt_mutex_lock(&myrpt
->lock
);
4620 l
->reconnects
= reconnects
;
4621 /* insert at end of queue */
4622 l
->max_retries
= MAX_RETRIES
;
4624 l
->max_retries
= MAX_RETRIES_PERM
;
4625 if (l
->isremote
) l
->retries
= l
->max_retries
+ 1;
4626 insque((struct qelem
*)l
,(struct qelem
*)myrpt
->links
.next
);
4628 rpt_mutex_unlock(&myrpt
->lock
);
4635 * Internet linking function
4638 static int function_ilink(struct rpt
*myrpt
, char *param
, char *digits
, int command_source
, struct rpt_link
*mylink
)
4641 char *val
, *s
, *s1
, *s2
;
4643 char digitbuf
[MAXNODESTR
],*strs
[MAXLINKLIST
];
4652 if (myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
|| myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].linkfundisable
)
4655 strncpy(digitbuf
,digits
,MAXNODESTR
- 1);
4658 printf("@@@@ ilink param = %s, digitbuf = %s\n", (param
)? param
: "(null)", digitbuf
);
4660 switch(myatoi(param
)){
4661 case 11: /* Perm Link off */
4662 case 1: /* Link off */
4663 if ((digitbuf
[0] == '0') && (myrpt
->lastlinknode
[0]))
4664 strcpy(digitbuf
,myrpt
->lastlinknode
);
4665 val
= node_lookup(myrpt
,digitbuf
);
4667 if(strlen(digitbuf
) >= myrpt
->longestnode
)
4671 strncpy(tmp
,val
,sizeof(tmp
) - 1);
4673 s1
= strsep(&s
,",");
4674 s2
= strsep(&s
,",");
4675 rpt_mutex_lock(&myrpt
->lock
);
4676 l
= myrpt
->links
.next
;
4677 /* try to find this one in queue */
4678 while(l
!= &myrpt
->links
){
4679 if (l
->name
[0] == '0')
4684 /* if found matching string */
4685 if (!strcmp(l
->name
, digitbuf
))
4689 if (l
!= &myrpt
->links
){ /* if found */
4690 struct ast_frame wf
;
4692 /* must use perm command on perm link */
4693 if ((myatoi(param
) < 10) &&
4694 (l
->max_retries
> MAX_RETRIES
))
4696 rpt_mutex_unlock(&myrpt
->lock
);
4699 strncpy(myrpt
->lastlinknode
,digitbuf
,MAXNODESTR
- 1);
4700 l
->retries
= l
->max_retries
+ 1;
4702 rpt_mutex_unlock(&myrpt
->lock
);
4703 wf
.frametype
= AST_FRAME_TEXT
;
4707 wf
.datalen
= strlen(discstr
) + 1;
4712 ast_write(l
->chan
,&wf
);
4713 if (ast_safe_sleep(l
->chan
,250) == -1) return DC_ERROR
;
4714 ast_softhangup(l
->chan
,AST_SOFTHANGUP_DEV
);
4716 rpt_telemetry(myrpt
, COMPLETE
, NULL
);
4719 rpt_mutex_unlock(&myrpt
->lock
);
4721 case 2: /* Link Monitor */
4722 case 3: /* Link transceive */
4723 case 12: /* Link Monitor permanent */
4724 case 13: /* Link transceive permanent */
4725 if ((digitbuf
[0] == '0') && (myrpt
->lastlinknode
[0]))
4726 strcpy(digitbuf
,myrpt
->lastlinknode
);
4727 /* Attempt connection */
4728 perma
= (atoi(param
) > 10) ? 1 : 0;
4729 mode
= (atoi(param
) & 1) ? 1 : 0;
4730 r
= connect_link(myrpt
, digitbuf
, mode
, perma
);
4733 rpt_telemetry(myrpt
, COMPLETE
, NULL
);
4740 rpt_telemetry(myrpt
, REMALREADY
, NULL
);
4744 rpt_telemetry(myrpt
, CONNFAIL
, NULL
);
4749 case 4: /* Enter Command Mode */
4751 /* if doesnt allow link cmd, or no links active, return */
4752 if (((command_source
!= SOURCE_RPT
) &&
4753 (command_source
!= SOURCE_PHONE
) &&
4754 (command_source
!= SOURCE_DPHONE
)) ||
4755 (myrpt
->links
.next
== &myrpt
->links
))
4758 /* if already in cmd mode, or selected self, fughetabahtit */
4759 if ((myrpt
->cmdnode
[0]) || (!strcmp(myrpt
->name
, digitbuf
))){
4761 rpt_telemetry(myrpt
, REMALREADY
, NULL
);
4764 if ((digitbuf
[0] == '0') && (myrpt
->lastlinknode
[0]))
4765 strcpy(digitbuf
,myrpt
->lastlinknode
);
4766 /* node must at least exist in list */
4767 val
= node_lookup(myrpt
,digitbuf
);
4769 if(strlen(digitbuf
) >= myrpt
->longestnode
)
4774 rpt_mutex_lock(&myrpt
->lock
);
4775 strcpy(myrpt
->lastlinknode
,digitbuf
);
4776 strncpy(myrpt
->cmdnode
, digitbuf
, sizeof(myrpt
->cmdnode
) - 1);
4777 rpt_mutex_unlock(&myrpt
->lock
);
4778 rpt_telemetry(myrpt
, REMGO
, NULL
);
4781 case 5: /* Status */
4782 rpt_telemetry(myrpt
, STATUS
, NULL
);
4785 case 15: /* Full Status */
4786 rpt_telemetry(myrpt
, FULLSTATUS
, NULL
);
4790 case 6: /* All Links Off, including permalinks */
4791 rpt_mutex_lock(&myrpt
->lock
);
4792 myrpt
->savednodes
[0] = 0;
4793 l
= myrpt
->links
.next
;
4794 /* loop through all links */
4795 while(l
!= &myrpt
->links
){
4796 struct ast_frame wf
;
4797 if (l
->name
[0] == '0') /* Skip any IAXRPT monitoring */
4802 /* Make a string of disconnected nodes for possible restoration */
4803 sprintf(tmp
,"%c%c%s",(l
->mode
) ? 'X' : 'M',(l
->perma
) ? 'P':'T',l
->name
);
4804 if(strlen(tmp
) + strlen(myrpt
->savednodes
) + 1 < MAXNODESTR
){
4805 if(myrpt
->savednodes
[0])
4806 strcat(myrpt
->savednodes
, ",");
4807 strcat(myrpt
->savednodes
, tmp
);
4809 l
->retries
= l
->max_retries
+ 1;
4810 l
->disced
= 2; /* Silently disconnect */
4811 rpt_mutex_unlock(&myrpt
->lock
);
4812 /* ast_log(LOG_NOTICE,"dumping link %s\n",l->name); */
4814 wf
.frametype
= AST_FRAME_TEXT
;
4818 wf
.datalen
= strlen(discstr
) + 1;
4823 ast_write(l
->chan
,&wf
);
4824 ast_safe_sleep(l
->chan
,250); /* It's dead already, why check the return value? */
4825 ast_softhangup(l
->chan
,AST_SOFTHANGUP_DEV
);
4827 rpt_mutex_lock(&myrpt
->lock
);
4830 rpt_mutex_unlock(&myrpt
->lock
);
4832 ast_log(LOG_NOTICE
,"Nodes disconnected: %s\n",myrpt
->savednodes
);
4833 rpt_telemetry(myrpt
, COMPLETE
, NULL
);
4836 case 7: /* Identify last node which keyed us up */
4837 rpt_telemetry(myrpt
, LASTNODEKEY
, NULL
);
4841 #ifdef _MDC_DECODE_H_
4843 myrpt
->lastunit
= 0xd00d;
4844 mdc1200_notify(myrpt
,NULL
,myrpt
->lastunit
);
4845 mdc1200_send(myrpt
,myrpt
->lastunit
);
4849 case 16: /* Restore links disconnected with "disconnect all links" command */
4850 strcpy(tmp
, myrpt
->savednodes
); /* Make a copy */
4851 finddelim(tmp
, strs
, MAXLINKLIST
); /* convert into substrings */
4852 for(i
= 0; tmp
[0] && strs
[i
] != NULL
&& i
< MAXLINKLIST
; i
++){
4854 mode
= (s1
[0] == 'X') ? 1 : 0;
4855 perma
= (s1
[1] == 'P') ? 1 : 0;
4856 connect_link(myrpt
, s1
+ 2, mode
, perma
); /* Try to reconnect */
4858 rpt_telemetry(myrpt
, COMPLETE
, NULL
);
4877 if (((myrpt
->p
.propagate_dtmf
) &&
4878 (command_source
== SOURCE_LNK
)) ||
4879 ((myrpt
->p
.propagate_phonedtmf
) &&
4880 ((command_source
== SOURCE_PHONE
) ||
4881 (command_source
== SOURCE_DPHONE
))))
4882 do_dtmf_local(myrpt
,
4883 remdtmfstr
[myatoi(param
) - 200]);
4889 return DC_INDETERMINATE
;
4896 static int function_autopatchup(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
4898 pthread_attr_t attr
;
4899 int i
, index
, paramlength
;
4902 char *paramlist
[20];
4904 static char *keywords
[] = {
4913 if (myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
|| myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].autopatchdisable
)
4917 printf("@@@@ Autopatch up\n");
4919 if(!myrpt
->callmode
){
4921 myrpt
->patchnoct
= 0;
4922 myrpt
->patchdialtime
= 0;
4923 myrpt
->patchfarenddisconnect
= 0;
4924 myrpt
->patchquiet
= 0;
4925 strncpy(myrpt
->patchcontext
, myrpt
->p
.ourcontext
, MAXPATCHCONTEXT
);
4928 /* Process parameter list */
4929 lparam
= ast_strdupa(param
);
4931 ast_log(LOG_ERROR
,"App_rpt out of memory on line %d\n",__LINE__
);
4934 paramlength
= finddelim(lparam
, paramlist
, 20);
4935 for(i
= 0; i
< paramlength
; i
++){
4936 index
= matchkeyword(paramlist
[i
], &value
, keywords
);
4938 value
= skipchars(value
, "= ");
4941 case 1: /* context */
4942 strncpy(myrpt
->patchcontext
, value
, MAXPATCHCONTEXT
- 1) ;
4945 case 2: /* dialtime */
4946 myrpt
->patchdialtime
= atoi(value
);
4949 case 3: /* farenddisconnect */
4950 myrpt
->patchfarenddisconnect
= atoi(value
);
4954 myrpt
->patchnoct
= atoi(value
);
4958 myrpt
->patchquiet
= atoi(value
);
4968 rpt_mutex_lock(&myrpt
->lock
);
4970 /* if on call, force * into current audio stream */
4972 if ((myrpt
->callmode
== 2) || (myrpt
->callmode
== 3)){
4973 myrpt
->mydtmf
= myrpt
->p
.endchar
;
4975 if (myrpt
->callmode
){
4976 rpt_mutex_unlock(&myrpt
->lock
);
4979 myrpt
->callmode
= 1;
4981 myrpt
->exten
[myrpt
->cidx
] = 0;
4982 rpt_mutex_unlock(&myrpt
->lock
);
4983 pthread_attr_init(&attr
);
4984 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
4985 ast_pthread_create(&myrpt
->rpt_call_thread
,&attr
,rpt_call
,(void *) myrpt
);
4993 static int function_autopatchdn(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
4995 if (myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
|| myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].autopatchdisable
)
4999 printf("@@@@ Autopatch down\n");
5001 rpt_mutex_lock(&myrpt
->lock
);
5003 if (!myrpt
->callmode
){
5004 rpt_mutex_unlock(&myrpt
->lock
);
5008 myrpt
->callmode
= 0;
5009 rpt_mutex_unlock(&myrpt
->lock
);
5010 rpt_telemetry(myrpt
, TERM
, NULL
);
5018 static int function_status(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
5024 if ((myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
) || (myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].userfundisable
))
5028 printf("@@@@ status param = %s, digitbuf = %s\n", (param
)? param
: "(null)", digitbuf
);
5030 switch(myatoi(param
)){
5031 case 1: /* System ID */
5032 rpt_telemetry(myrpt
, ID1
, NULL
);
5034 case 2: /* System Time */
5035 rpt_telemetry(myrpt
, STATS_TIME
, NULL
);
5037 case 3: /* app_rpt.c version */
5038 rpt_telemetry(myrpt
, STATS_VERSION
, NULL
);
5042 return DC_INDETERMINATE
;
5046 * Macro-oni (without Salami)
5049 static int function_macro(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
5058 printf("@@@@ macro-oni param = %s, digitbuf = %s\n", (param
)? param
: "(null)", digitbuf
);
5060 if(strlen(digitbuf
) < 1) /* needs 1 digit */
5061 return DC_INDETERMINATE
;
5063 for(i
= 0 ; i
< digitbuf
[i
] ; i
++) {
5064 if((digitbuf
[i
] < '0') || (digitbuf
[i
] > '9'))
5068 if (*digitbuf
== '0') val
= myrpt
->p
.startupmacro
;
5069 else val
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->p
.macro
, digitbuf
);
5070 /* param was 1 for local buf */
5072 if (strlen(digitbuf
) < myrpt
->macro_longest
)
5073 return DC_INDETERMINATE
;
5074 rpt_telemetry(myrpt
, MACRO_NOTFOUND
, NULL
);
5077 rpt_mutex_lock(&myrpt
->lock
);
5078 if ((MAXMACRO
- strlen(myrpt
->macrobuf
)) < strlen(val
))
5080 rpt_mutex_unlock(&myrpt
->lock
);
5081 rpt_telemetry(myrpt
, MACRO_BUSY
, NULL
);
5084 myrpt
->macrotimer
= MACROTIME
;
5085 strncat(myrpt
->macrobuf
, val
, MAXMACRO
- strlen(myrpt
->macrobuf
) - 1);
5086 rpt_mutex_unlock(&myrpt
->lock
);
5091 * COP - Control operator
5094 static int function_cop(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
5101 switch(myatoi(param
)){
5102 case 1: /* System reset */
5103 system("killall -9 asterisk");
5107 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
= 0;
5108 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "RPTENA");
5112 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
= 1;
5115 case 4: /* test tone on */
5116 if (myrpt
->stopgen
< 0)
5123 rpt_telemetry(myrpt
, TEST_TONE
, NULL
);
5127 case 5: /* Disgorge variables to log for debug purposes */
5128 myrpt
->disgorgetime
= time(NULL
) + 10; /* Do it 10 seconds later */
5131 case 6: /* Simulate COR being activated (phone only) */
5132 if (command_source
!= SOURCE_PHONE
) return DC_INDETERMINATE
;
5136 case 7: /* Time out timer enable */
5137 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].totdisable
= 0;
5138 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "TOTENA");
5141 case 8: /* Time out timer disable */
5142 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].totdisable
= 1;
5143 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "TOTDIS");
5146 case 9: /* Autopatch enable */
5147 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].autopatchdisable
= 0;
5148 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "APENA");
5151 case 10: /* Autopatch disable */
5152 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].autopatchdisable
= 1;
5153 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "APDIS");
5156 case 11: /* Link Enable */
5157 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].linkfundisable
= 0;
5158 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "LNKENA");
5161 case 12: /* Link Disable */
5162 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].linkfundisable
= 1;
5163 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "LNKDIS");
5166 case 13: /* Query System State */
5167 string
[0] = string
[1] = 'S';
5168 string
[2] = myrpt
->p
.sysstate_cur
+ '0';
5170 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) string
);
5173 case 14: /* Change System State */
5174 if(strlen(digitbuf
) == 0)
5176 if((digitbuf
[0] < '0') || (digitbuf
[0] > '9'))
5178 myrpt
->p
.sysstate_cur
= digitbuf
[0] - '0';
5179 string
[0] = string
[1] = 'S';
5180 string
[2] = myrpt
->p
.sysstate_cur
+ '0';
5182 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) string
);
5185 case 15: /* Scheduler Enable */
5186 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].schedulerdisable
= 0;
5187 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "SKENA");
5190 case 16: /* Scheduler Disable */
5191 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].schedulerdisable
= 1;
5192 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "SKDIS");
5195 case 17: /* User functions Enable */
5196 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].userfundisable
= 0;
5197 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "UFENA");
5200 case 18: /* User Functions Disable */
5201 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].userfundisable
= 1;
5202 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "UFDIS");
5205 case 19: /* Alternate Tail Enable */
5206 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].alternatetail
= 1;
5207 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "ATENA");
5210 case 20: /* Alternate Tail Disable */
5211 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].alternatetail
= 0;
5212 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "ATDIS");
5215 return DC_INDETERMINATE
;
5219 * Collect digits one by one until something matches
5222 static int collect_function_digits(struct rpt
*myrpt
, char *digits
,
5223 int command_source
, struct rpt_link
*mylink
)
5226 char *stringp
,*action
,*param
,*functiondigits
;
5227 char function_table_name
[30] = "";
5228 char workstring
[200];
5230 struct ast_variable
*vp
;
5233 printf("@@@@ Digits collected: %s, source: %d\n", digits
, command_source
);
5235 if (command_source
== SOURCE_DPHONE
) {
5236 if (!myrpt
->p
.dphone_functions
) return DC_INDETERMINATE
;
5237 strncpy(function_table_name
, myrpt
->p
.dphone_functions
, sizeof(function_table_name
) - 1);
5239 else if (command_source
== SOURCE_PHONE
) {
5240 if (!myrpt
->p
.phone_functions
) return DC_INDETERMINATE
;
5241 strncpy(function_table_name
, myrpt
->p
.phone_functions
, sizeof(function_table_name
) - 1);
5243 else if (command_source
== SOURCE_LNK
)
5244 strncpy(function_table_name
, myrpt
->p
.link_functions
, sizeof(function_table_name
) - 1);
5246 strncpy(function_table_name
, myrpt
->p
.functions
, sizeof(function_table_name
) - 1);
5247 vp
= ast_variable_browse(myrpt
->cfg
, function_table_name
);
5249 if(!strncasecmp(vp
->name
, digits
, strlen(vp
->name
)))
5256 n
= myrpt
->longestfunc
;
5257 if (command_source
== SOURCE_LNK
) n
= myrpt
->link_longestfunc
;
5259 if (command_source
== SOURCE_PHONE
) n
= myrpt
->phone_longestfunc
;
5261 if (command_source
== SOURCE_DPHONE
) n
= myrpt
->dphone_longestfunc
;
5263 if(strlen(digits
) >= n
)
5266 return DC_INDETERMINATE
;
5268 /* Found a match, retrieve value part and parse */
5269 strncpy(workstring
, vp
->value
, sizeof(workstring
) - 1 );
5270 stringp
= workstring
;
5271 action
= strsep(&stringp
, ",");
5274 printf("@@@@ action: %s, param = %s\n",action
, (param
) ? param
: "(null)");
5275 /* Look up the action */
5276 for(i
= 0 ; i
< (sizeof(function_table
)/sizeof(struct function_table_tag
)); i
++){
5277 if(!strncasecmp(action
, function_table
[i
].action
, strlen(action
)))
5281 printf("@@@@ table index i = %d\n",i
);
5282 if(i
== (sizeof(function_table
)/sizeof(struct function_table_tag
))){
5283 /* Error, action not in table */
5286 if(function_table
[i
].function
== NULL
){
5287 /* Error, function undefined */
5289 printf("@@@@ NULL for action: %s\n",action
);
5292 functiondigits
= digits
+ strlen(vp
->name
);
5293 return (*function_table
[i
].function
)(myrpt
, param
, functiondigits
, command_source
, mylink
);
5297 static void handle_link_data(struct rpt
*myrpt
, struct rpt_link
*mylink
,
5300 char tmp
[512],cmd
[300] = "",dest
[300],src
[300],c
;
5303 struct ast_frame wf
;
5305 wf
.frametype
= AST_FRAME_TEXT
;
5309 wf
.datalen
= strlen(str
) + 1;
5311 /* put string in our buffer */
5312 strncpy(tmp
,str
,sizeof(tmp
) - 1);
5314 if (!strcmp(tmp
,discstr
))
5317 mylink
->retries
= mylink
->max_retries
+ 1;
5318 ast_softhangup(mylink
->chan
,AST_SOFTHANGUP_DEV
);
5323 rpt_mutex_lock(&myrpt
->lock
);
5324 strcpy(mylink
->linklist
,tmp
+ 2);
5325 time(&mylink
->linklistreceived
);
5326 rpt_mutex_unlock(&myrpt
->lock
);
5327 if (debug
> 6) ast_log(LOG_NOTICE
,"@@@@ node %s recieved node list %s from node %s\n",
5328 myrpt
->name
,tmp
,mylink
->name
);
5333 if (sscanf(tmp
,"%s %s %x",cmd
,src
,&seq
) != 3)
5335 ast_log(LOG_WARNING
, "Unable to parse ident string %s\n",str
);
5338 mdc1200_notify(myrpt
,src
,seq
);
5343 if (sscanf(tmp
,"%s %s %s %d %c",cmd
,dest
,src
,&seq
,&c
) != 5)
5345 ast_log(LOG_WARNING
, "Unable to parse link string %s\n",str
);
5348 if (strcmp(cmd
,"D"))
5350 ast_log(LOG_WARNING
, "Unable to parse link string %s\n",str
);
5356 strcpy(dest
,myrpt
->name
);
5359 /* if not for me, redistribute to all links */
5360 if (strcmp(dest
,myrpt
->name
))
5362 l
= myrpt
->links
.next
;
5363 /* see if this is one in list */
5364 while(l
!= &myrpt
->links
)
5366 if (l
->name
[0] == '0')
5371 /* dont send back from where it came */
5372 if ((l
== mylink
) || (!strcmp(l
->name
,mylink
->name
)))
5377 /* if it is, send it and we're done */
5378 if (!strcmp(l
->name
,dest
))
5380 /* send, but not to src */
5381 if (strcmp(l
->name
,src
)) {
5383 if (l
->chan
) ast_write(l
->chan
,&wf
);
5389 l
= myrpt
->links
.next
;
5390 /* otherwise, send it to all of em */
5391 while(l
!= &myrpt
->links
)
5393 if (l
->name
[0] == '0')
5398 /* dont send back from where it came */
5399 if ((l
== mylink
) || (!strcmp(l
->name
,mylink
->name
)))
5404 /* send, but not to src */
5405 if (strcmp(l
->name
,src
)) {
5407 if (l
->chan
) ast_write(l
->chan
,&wf
);
5413 if (myrpt
->p
.archivedir
)
5417 sprintf(str
,"DTMF,%s,%c",mylink
->name
,c
);
5418 donodelog(myrpt
,str
);
5420 c
= func_xlat(myrpt
,c
,&myrpt
->p
.outxlat
);
5422 rpt_mutex_lock(&myrpt
->lock
);
5423 if (c
== myrpt
->p
.endchar
) myrpt
->stopgen
= 1;
5424 if (myrpt
->callmode
== 1)
5426 myrpt
->exten
[myrpt
->cidx
++] = c
;
5427 myrpt
->exten
[myrpt
->cidx
] = 0;
5428 /* if this exists */
5429 if (ast_exists_extension(myrpt
->pchannel
,myrpt
->patchcontext
,myrpt
->exten
,1,NULL
))
5431 myrpt
->callmode
= 2;
5432 if(!myrpt
->patchquiet
){
5433 rpt_mutex_unlock(&myrpt
->lock
);
5434 rpt_telemetry(myrpt
,PROC
,NULL
);
5435 rpt_mutex_lock(&myrpt
->lock
);
5438 /* if can continue, do so */
5439 if (!ast_canmatch_extension(myrpt
->pchannel
,myrpt
->patchcontext
,myrpt
->exten
,1,NULL
))
5441 /* call has failed, inform user */
5442 myrpt
->callmode
= 4;
5445 if (c
== myrpt
->p
.funcchar
)
5447 myrpt
->rem_dtmfidx
= 0;
5448 myrpt
->rem_dtmfbuf
[myrpt
->rem_dtmfidx
] = 0;
5449 time(&myrpt
->rem_dtmf_time
);
5450 rpt_mutex_unlock(&myrpt
->lock
);
5453 else if (myrpt
->rem_dtmfidx
< 0)
5455 if ((myrpt
->callmode
== 2) || (myrpt
->callmode
== 3))
5459 if (myrpt
->p
.propagate_dtmf
) do_dtmf_local(myrpt
,c
);
5460 if (myrpt
->p
.propagate_phonedtmf
) do_dtmf_phone(myrpt
,mylink
,c
);
5461 rpt_mutex_unlock(&myrpt
->lock
);
5464 else if ((c
!= myrpt
->p
.endchar
) && (myrpt
->rem_dtmfidx
>= 0))
5466 time(&myrpt
->rem_dtmf_time
);
5467 if (myrpt
->rem_dtmfidx
< MAXDTMF
)
5469 myrpt
->rem_dtmfbuf
[myrpt
->rem_dtmfidx
++] = c
;
5470 myrpt
->rem_dtmfbuf
[myrpt
->rem_dtmfidx
] = 0;
5472 rpt_mutex_unlock(&myrpt
->lock
);
5473 strncpy(cmd
, myrpt
->rem_dtmfbuf
, sizeof(cmd
) - 1);
5474 res
= collect_function_digits(myrpt
, cmd
, SOURCE_LNK
, mylink
);
5475 rpt_mutex_lock(&myrpt
->lock
);
5479 case DC_INDETERMINATE
:
5483 myrpt
->rem_dtmfidx
= 0;
5484 myrpt
->rem_dtmfbuf
[0] = 0;
5489 case DC_COMPLETEQUIET
:
5490 myrpt
->totalexecdcommands
++;
5491 myrpt
->dailyexecdcommands
++;
5492 strncpy(myrpt
->lastdtmfcommand
, cmd
, MAXDTMF
-1);
5493 myrpt
->lastdtmfcommand
[MAXDTMF
-1] = '\0';
5494 myrpt
->rem_dtmfbuf
[0] = 0;
5495 myrpt
->rem_dtmfidx
= -1;
5496 myrpt
->rem_dtmf_time
= 0;
5501 myrpt
->rem_dtmfbuf
[0] = 0;
5502 myrpt
->rem_dtmfidx
= -1;
5503 myrpt
->rem_dtmf_time
= 0;
5509 rpt_mutex_unlock(&myrpt
->lock
);
5513 static void handle_link_phone_dtmf(struct rpt
*myrpt
, struct rpt_link
*mylink
,
5520 if (myrpt
->p
.archivedir
)
5524 sprintf(str
,"DTMF(P),%s,%c",mylink
->name
,c
);
5525 donodelog(myrpt
,str
);
5527 rpt_mutex_lock(&myrpt
->lock
);
5528 if (c
== myrpt
->p
.endchar
)
5533 rpt_mutex_unlock(&myrpt
->lock
);
5537 if (myrpt
->cmdnode
[0])
5539 myrpt
->cmdnode
[0] = 0;
5540 myrpt
->dtmfidx
= -1;
5541 myrpt
->dtmfbuf
[0] = 0;
5542 rpt_mutex_unlock(&myrpt
->lock
);
5543 rpt_telemetry(myrpt
,COMPLETE
,NULL
);
5547 if (myrpt
->cmdnode
[0])
5549 rpt_mutex_unlock(&myrpt
->lock
);
5550 send_link_dtmf(myrpt
,c
);
5553 if (myrpt
->callmode
== 1)
5555 myrpt
->exten
[myrpt
->cidx
++] = c
;
5556 myrpt
->exten
[myrpt
->cidx
] = 0;
5557 /* if this exists */
5558 if (ast_exists_extension(myrpt
->pchannel
,myrpt
->patchcontext
,myrpt
->exten
,1,NULL
))
5560 myrpt
->callmode
= 2;
5561 if(!myrpt
->patchquiet
){
5562 rpt_mutex_unlock(&myrpt
->lock
);
5563 rpt_telemetry(myrpt
,PROC
,NULL
);
5564 rpt_mutex_lock(&myrpt
->lock
);
5567 /* if can continue, do so */
5568 if (!ast_canmatch_extension(myrpt
->pchannel
,myrpt
->patchcontext
,myrpt
->exten
,1,NULL
))
5570 /* call has failed, inform user */
5571 myrpt
->callmode
= 4;
5574 if ((myrpt
->callmode
== 2) || (myrpt
->callmode
== 3))
5578 if (c
== myrpt
->p
.funcchar
)
5580 myrpt
->rem_dtmfidx
= 0;
5581 myrpt
->rem_dtmfbuf
[myrpt
->rem_dtmfidx
] = 0;
5582 time(&myrpt
->rem_dtmf_time
);
5583 rpt_mutex_unlock(&myrpt
->lock
);
5586 else if ((c
!= myrpt
->p
.endchar
) && (myrpt
->rem_dtmfidx
>= 0))
5588 time(&myrpt
->rem_dtmf_time
);
5589 if (myrpt
->rem_dtmfidx
< MAXDTMF
)
5591 myrpt
->rem_dtmfbuf
[myrpt
->rem_dtmfidx
++] = c
;
5592 myrpt
->rem_dtmfbuf
[myrpt
->rem_dtmfidx
] = 0;
5594 rpt_mutex_unlock(&myrpt
->lock
);
5595 strncpy(cmd
, myrpt
->rem_dtmfbuf
, sizeof(cmd
) - 1);
5596 switch(mylink
->phonemode
)
5599 res
= collect_function_digits(myrpt
, cmd
,
5600 SOURCE_PHONE
, mylink
);
5603 res
= collect_function_digits(myrpt
, cmd
,
5604 SOURCE_DPHONE
,mylink
);
5607 res
= collect_function_digits(myrpt
, cmd
,
5608 SOURCE_LNK
, mylink
);
5612 rpt_mutex_lock(&myrpt
->lock
);
5616 case DC_INDETERMINATE
:
5624 myrpt
->rem_dtmfidx
= 0;
5625 myrpt
->rem_dtmfbuf
[0] = 0;
5630 case DC_COMPLETEQUIET
:
5631 myrpt
->totalexecdcommands
++;
5632 myrpt
->dailyexecdcommands
++;
5633 strncpy(myrpt
->lastdtmfcommand
, cmd
, MAXDTMF
-1);
5634 myrpt
->lastdtmfcommand
[MAXDTMF
-1] = '\0';
5635 myrpt
->rem_dtmfbuf
[0] = 0;
5636 myrpt
->rem_dtmfidx
= -1;
5637 myrpt
->rem_dtmf_time
= 0;
5642 myrpt
->rem_dtmfbuf
[0] = 0;
5643 myrpt
->rem_dtmfidx
= -1;
5644 myrpt
->rem_dtmf_time
= 0;
5650 rpt_mutex_unlock(&myrpt
->lock
);
5654 /* Doug Hall RBI-1 serial data definitions:
5656 * Byte 0: Expansion external outputs
5658 * Bits 0-3 are BAND as follows:
5659 * Bits 4-5 are POWER bits as follows:
5663 * Bits 6-7 are always set
5665 * Bits 0-3 MHZ in BCD format
5666 * Bits 4-5 are offset as follows:
5670 * 03 - minus minus (whatever that is)
5671 * Bit 6 is the 0/5 KHZ bit
5672 * Bit 7 is always set
5674 * Bits 0-3 are 10 KHZ in BCD format
5675 * Bits 4-7 are 100 KHZ in BCD format
5676 * Byte 4: PL Tone code and encode/decode enable bits
5677 * Bits 0-5 are PL tone code (comspec binary codes)
5678 * Bit 6 is encode enable/disable
5679 * Bit 7 is decode enable/disable
5682 /* take the frequency from the 10 mhz digits (and up) and convert it
5685 static int rbi_mhztoband(char *str
)
5689 i
= atoi(str
) / 10; /* get the 10's of mhz */
5720 /* take a PL frequency and turn it into a code */
5721 static int rbi_pltocode(char *str
)
5726 s
= strchr(str
,'.');
5728 if (s
) i
= atoi(s
+ 1);
5729 i
+= atoi(str
) * 10;
5813 * Shift out a formatted serial bit stream
5816 static void rbi_out_parallel(struct rpt
*myrpt
,unsigned char *data
)
5821 static volatile long long delayvar
;
5823 for(i
= 0 ; i
< 5 ; i
++){
5825 for(j
= 0 ; j
< 8 ; j
++){
5827 outb(d
,myrpt
->p
.iobase
);
5829 for(delayvar
= 1; delayvar
< 15000; delayvar
++);
5831 outb(d
| 2,myrpt
->p
.iobase
);
5833 for(delayvar
= 1; delayvar
< 30000; delayvar
++);
5834 outb(d
,myrpt
->p
.iobase
);
5836 for(delayvar
= 1; delayvar
< 10000; delayvar
++);
5840 for(delayvar
= 1; delayvar
< 50000; delayvar
++);
5844 static void rbi_out(struct rpt
*myrpt
,unsigned char *data
)
5846 struct dahdi_radio_param r
;
5848 memset(&r
,0,sizeof(struct dahdi_radio_param
));
5849 r
.radpar
= DAHDI_RADPAR_REMMODE
;
5850 r
.data
= DAHDI_RADPAR_REM_RBI1
;
5851 /* if setparam ioctl fails, its probably not a pciradio card */
5852 if (ioctl(myrpt
->zaprxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&r
) == -1)
5854 rbi_out_parallel(myrpt
,data
);
5857 r
.radpar
= DAHDI_RADPAR_REMCOMMAND
;
5858 memcpy(&r
.data
,data
,5);
5859 if (ioctl(myrpt
->zaprxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&r
) == -1)
5861 ast_log(LOG_WARNING
,"Cannot send RBI command for channel %s\n",myrpt
->zaprxchannel
->name
);
5866 static int serial_remote_io(struct rpt
*myrpt
, unsigned char *txbuf
, int txbytes
,
5867 unsigned char *rxbuf
, int rxmaxbytes
, int asciiflag
)
5869 int i
,j
,index
,oldmode
,olddata
;
5870 struct dahdi_radio_param prm
;
5874 printf("String output was: ");
5875 for(i
= 0; i
< txbytes
; i
++)
5876 printf("%02X ", (unsigned char ) txbuf
[i
]);
5879 if (myrpt
->iofd
> 0) /* if to do out a serial port */
5881 if (rxmaxbytes
&& rxbuf
) tcflush(myrpt
->iofd
,TCIFLUSH
);
5882 if (write(myrpt
->iofd
,txbuf
,txbytes
) != txbytes
) return -1;
5883 if ((!rxmaxbytes
) || (rxbuf
== NULL
)) return(0);
5884 memset(rxbuf
,0,rxmaxbytes
);
5885 for(i
= 0; i
< rxmaxbytes
; i
++)
5887 j
= read(myrpt
->iofd
,&c
,1);
5888 if (j
< 1) return(i
);
5893 if (c
== '\r') break;
5897 printf("String returned was: ");
5898 for(j
= 0; j
< i
; j
++)
5899 printf("%02X ", (unsigned char ) rxbuf
[j
]);
5905 /* if not a zap channel, cant use pciradio stuff */
5906 if (myrpt
->rxchannel
!= myrpt
->zaprxchannel
) return -1;
5908 prm
.radpar
= DAHDI_RADPAR_UIOMODE
;
5909 if (ioctl(myrpt
->zaprxchannel
->fds
[0],DAHDI_RADIO_GETPARAM
,&prm
) == -1) return -1;
5911 prm
.radpar
= DAHDI_RADPAR_UIODATA
;
5912 if (ioctl(myrpt
->zaprxchannel
->fds
[0],DAHDI_RADIO_GETPARAM
,&prm
) == -1) return -1;
5914 prm
.radpar
= DAHDI_RADPAR_REMMODE
;
5915 if (asciiflag
& 1) prm
.data
= DAHDI_RADPAR_REM_SERIAL_ASCII
;
5916 else prm
.data
= DAHDI_RADPAR_REM_SERIAL
;
5917 if (ioctl(myrpt
->zaprxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&prm
) == -1) return -1;
5921 if (ioctl(myrpt
->zaprxchannel
->fds
[0],DAHDI_HOOK
,&i
) == -1) return -1;
5924 prm
.radpar
= DAHDI_RADPAR_REMCOMMAND
;
5925 prm
.data
= rxmaxbytes
;
5926 memcpy(prm
.buf
,txbuf
,txbytes
);
5927 prm
.index
= txbytes
;
5928 if (ioctl(myrpt
->zaprxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&prm
) == -1) return -1;
5932 memcpy(rxbuf
,prm
.buf
,prm
.index
);
5935 prm
.radpar
= DAHDI_RADPAR_REMMODE
;
5936 prm
.data
= DAHDI_RADPAR_REM_NONE
;
5937 if (ioctl(myrpt
->zaprxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&prm
) == -1) return -1;
5941 if (ioctl(myrpt
->zaprxchannel
->fds
[0],DAHDI_HOOK
,&i
) == -1) return -1;
5943 prm
.radpar
= DAHDI_RADPAR_UIOMODE
;
5945 if (ioctl(myrpt
->zaprxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&prm
) == -1) return -1;
5946 prm
.radpar
= DAHDI_RADPAR_UIODATA
;
5948 if (ioctl(myrpt
->zaprxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&prm
) == -1) return -1;
5952 static int civ_cmd(struct rpt
*myrpt
,unsigned char *cmd
, int cmdlen
)
5954 unsigned char rxbuf
[100];
5957 rv
= serial_remote_io(myrpt
,cmd
,cmdlen
,rxbuf
,cmdlen
+ 6,0);
5958 if (rv
== -1) return(-1);
5959 if (rv
!= (cmdlen
+ 6)) return(1);
5960 for(i
= 0; i
< 6; i
++)
5961 if (rxbuf
[i
] != cmd
[i
]) return(1);
5962 if (rxbuf
[cmdlen
] != 0xfe) return(1);
5963 if (rxbuf
[cmdlen
+ 1] != 0xfe) return(1);
5964 if (rxbuf
[cmdlen
+ 4] != 0xfb) return(1);
5965 if (rxbuf
[cmdlen
+ 5] != 0xfd) return(1);
5969 static int sendkenwood(struct rpt
*myrpt
,char *txstr
, char *rxstr
)
5973 if (debug
) printf("Send to kenwood: %s\n",txstr
);
5974 i
= serial_remote_io(myrpt
, (unsigned char *)txstr
, strlen(txstr
),
5975 (unsigned char *)rxstr
,RAD_SERIAL_BUFLEN
- 1,3);
5976 if (i
< 0) return -1;
5977 if ((i
> 0) && (rxstr
[i
- 1] == '\r'))
5979 if (debug
) printf("Got from kenwood: %s\n",rxstr
);
5983 /* take a PL frequency and turn it into a code */
5984 static int kenwood_pltocode(char *str
)
5989 s
= strchr(str
,'.');
5991 if (s
) i
= atoi(s
+ 1);
5992 i
+= atoi(str
) * 10;
6075 static int sendrxkenwood(struct rpt
*myrpt
, char *txstr
, char *rxstr
,
6080 for(i
= 0;i
< KENWOOD_RETRIES
;i
++)
6082 j
= sendkenwood(myrpt
,txstr
,rxstr
);
6083 if (j
< 0) return(j
);
6084 if (j
== 0) continue;
6085 if (!strncmp(rxstr
,cmpstr
,strlen(cmpstr
))) return(0);
6090 static int setkenwood(struct rpt
*myrpt
)
6092 char rxstr
[RAD_SERIAL_BUFLEN
],txstr
[RAD_SERIAL_BUFLEN
],freq
[20];
6093 char mhz
[MAXREMSTR
],offset
[20],band
,decimals
[MAXREMSTR
],band1
,band2
;
6095 int offsets
[] = {0,2,1};
6096 int powers
[] = {2,1,0};
6098 if (sendrxkenwood(myrpt
,"VMC 0,0\r",rxstr
,"VMC") < 0) return -1;
6099 split_freq(mhz
, decimals
, myrpt
->freq
);
6100 if (atoi(mhz
) > 400)
6105 strcpy(offset
,"005000000");
6112 strcpy(offset
,"000600000");
6114 strcpy(freq
,"000000");
6115 strncpy(freq
,decimals
,strlen(decimals
));
6116 sprintf(txstr
,"VW %c,%05d%s,0,%d,0,%d,%d,,%02d,,%02d,%s\r",
6117 band
,atoi(mhz
),freq
,offsets
[(int)myrpt
->offset
],
6118 (myrpt
->txplon
!= 0),(myrpt
->rxplon
!= 0),
6119 kenwood_pltocode(myrpt
->txpl
),kenwood_pltocode(myrpt
->rxpl
),
6121 if (sendrxkenwood(myrpt
,txstr
,rxstr
,"VW") < 0) return -1;
6122 sprintf(txstr
,"RBN %c\r",band2
);
6123 if (sendrxkenwood(myrpt
,txstr
,rxstr
,"RBN") < 0) return -1;
6124 sprintf(txstr
,"PC %c,%d\r",band1
,powers
[(int)myrpt
->powerlevel
]);
6125 if (sendrxkenwood(myrpt
,txstr
,rxstr
,"PC") < 0) return -1;
6129 static int setrbi(struct rpt
*myrpt
)
6131 char tmp
[MAXREMSTR
] = "",*s
;
6132 unsigned char rbicmd
[5];
6133 int band
,txoffset
= 0,txpower
= 0,rxpl
;
6135 /* must be a remote system */
6136 if (!myrpt
->remote
) return(0);
6137 /* must have rbi hardware */
6138 if (strncmp(myrpt
->remote
,remote_rig_rbi
,3)) return(0);
6139 if (setrbi_check(myrpt
) == -1) return(-1);
6140 strncpy(tmp
, myrpt
->freq
, sizeof(tmp
) - 1);
6141 s
= strchr(tmp
,'.');
6142 /* if no decimal, is invalid */
6146 printf("@@@@ Frequency needs a decimal\n");
6151 if (strlen(tmp
) < 2){
6153 printf("@@@@ Bad MHz digits: %s\n", tmp
);
6159 printf("@@@@ Bad KHz digits: %s\n", s
);
6163 if ((s
[2] != '0') && (s
[2] != '5')){
6165 printf("@@@@ KHz must end in 0 or 5: %c\n", s
[2]);
6169 band
= rbi_mhztoband(tmp
);
6172 printf("@@@@ Bad Band: %s\n", tmp
);
6176 rxpl
= rbi_pltocode(myrpt
->rxpl
);
6180 printf("@@@@ Bad TX PL: %s\n", myrpt
->rxpl
);
6185 switch(myrpt
->offset
)
6197 switch(myrpt
->powerlevel
)
6210 rbicmd
[1] = band
| txpower
| 0xc0;
6211 rbicmd
[2] = (*(s
- 2) - '0') | txoffset
| 0x80;
6212 if (s
[2] == '5') rbicmd
[2] |= 0x40;
6213 rbicmd
[3] = ((*s
- '0') << 4) + (s
[1] - '0');
6215 if (myrpt
->txplon
) rbicmd
[4] |= 0x40;
6216 if (myrpt
->rxplon
) rbicmd
[4] |= 0x80;
6217 rbi_out(myrpt
,rbicmd
);
6221 static int setrbi_check(struct rpt
*myrpt
)
6223 char tmp
[MAXREMSTR
] = "",*s
;
6226 /* must be a remote system */
6227 if (!myrpt
->remote
) return(0);
6228 /* must have rbi hardware */
6229 if (strncmp(myrpt
->remote
,remote_rig_rbi
,3)) return(0);
6230 strncpy(tmp
, myrpt
->freq
, sizeof(tmp
) - 1);
6231 s
= strchr(tmp
,'.');
6232 /* if no decimal, is invalid */
6236 printf("@@@@ Frequency needs a decimal\n");
6241 if (strlen(tmp
) < 2){
6243 printf("@@@@ Bad MHz digits: %s\n", tmp
);
6249 printf("@@@@ Bad KHz digits: %s\n", s
);
6253 if ((s
[2] != '0') && (s
[2] != '5')){
6255 printf("@@@@ KHz must end in 0 or 5: %c\n", s
[2]);
6259 band
= rbi_mhztoband(tmp
);
6262 printf("@@@@ Bad Band: %s\n", tmp
);
6266 txpl
= rbi_pltocode(myrpt
->txpl
);
6270 printf("@@@@ Bad TX PL: %s\n", myrpt
->txpl
);
6276 static int check_freq_kenwood(int m
, int d
, int *defmode
)
6278 int dflmd
= REM_MODE_FM
;
6280 if (m
== 144){ /* 2 meters */
6284 else if((m
>= 145) && (m
< 148)){
6287 else if((m
>= 430) && (m
< 450)){ /* 70 centimeters */
6301 /* Check for valid rbi frequency */
6302 /* Hard coded limits now, configurable later, maybe? */
6304 static int check_freq_rbi(int m
, int d
, int *defmode
)
6306 int dflmd
= REM_MODE_FM
;
6308 if(m
== 50){ /* 6 meters */
6312 else if((m
>= 51) && ( m
< 54)){
6315 else if(m
== 144){ /* 2 meters */
6319 else if((m
>= 145) && (m
< 148)){
6322 else if((m
>= 222) && (m
< 225)){ /* 1.25 meters */
6325 else if((m
>= 430) && (m
< 450)){ /* 70 centimeters */
6328 else if((m
>= 1240) && (m
< 1300)){ /* 23 centimeters */
6342 * Convert decimals of frequency to int
6345 static int decimals2int(char *fraction
)
6348 char len
= strlen(fraction
);
6349 int multiplier
= 100000;
6354 for( i
= 0 ; i
< len
; i
++, multiplier
/= 10)
6355 res
+= (fraction
[i
] - '0') * multiplier
;
6361 * Split frequency into mhz and decimals
6364 static int split_freq(char *mhz
, char *decimals
, char *freq
)
6366 char freq_copy
[MAXREMSTR
];
6369 decp
= strchr(strncpy(freq_copy
, freq
, MAXREMSTR
),'.');
6372 strncpy(mhz
, freq_copy
, MAXREMSTR
);
6373 strcpy(decimals
, "00000");
6374 strncpy(decimals
, decp
, strlen(decp
));
6384 * Split ctcss frequency into hertz and decimal
6387 static int split_ctcss_freq(char *hertz
, char *decimal
, char *freq
)
6389 char freq_copy
[MAXREMSTR
];
6392 decp
= strchr(strncpy(freq_copy
, freq
, MAXREMSTR
),'.');
6395 strncpy(hertz
, freq_copy
, MAXREMSTR
);
6396 strncpy(decimal
, decp
, strlen(decp
));
6397 decimal
[strlen(decp
)] = '\0';
6407 * FT-897 I/O handlers
6410 /* Check to see that the frequency is valid */
6411 /* Hard coded limits now, configurable later, maybe? */
6414 static int check_freq_ft897(int m
, int d
, int *defmode
)
6416 int dflmd
= REM_MODE_FM
;
6418 if(m
== 1){ /* 160 meters */
6419 dflmd
= REM_MODE_LSB
;
6423 else if(m
== 3){ /* 80 meters */
6424 dflmd
= REM_MODE_LSB
;
6428 else if(m
== 7){ /* 40 meters */
6429 dflmd
= REM_MODE_LSB
;
6433 else if(m
== 14){ /* 20 meters */
6434 dflmd
= REM_MODE_USB
;
6438 else if(m
== 18){ /* 17 meters */
6439 dflmd
= REM_MODE_USB
;
6440 if((d
< 6800) || (d
> 16800))
6443 else if(m
== 21){ /* 15 meters */
6444 dflmd
= REM_MODE_USB
;
6445 if((d
< 20000) || (d
> 45000))
6448 else if(m
== 24){ /* 12 meters */
6449 dflmd
= REM_MODE_USB
;
6450 if((d
< 89000) || (d
> 99000))
6453 else if(m
== 28){ /* 10 meters */
6454 dflmd
= REM_MODE_USB
;
6458 dflmd
= REM_MODE_FM
;
6460 dflmd
= REM_MODE_USB
;
6464 else if(m
== 50){ /* 6 meters */
6466 dflmd
= REM_MODE_FM
;
6468 dflmd
= REM_MODE_USB
;
6471 else if((m
>= 51) && ( m
< 54)){
6472 dflmd
= REM_MODE_FM
;
6474 else if(m
== 144){ /* 2 meters */
6476 dflmd
= REM_MODE_FM
;
6478 dflmd
= REM_MODE_USB
;
6480 else if((m
>= 145) && (m
< 148)){
6481 dflmd
= REM_MODE_FM
;
6483 else if((m
>= 430) && (m
< 450)){ /* 70 centimeters */
6485 dflmd
= REM_MODE_USB
;
6487 dflmd
= REM_MODE_FM
;
6500 * Set a new frequency for the FT897
6503 static int set_freq_ft897(struct rpt
*myrpt
, char *newfreq
)
6505 unsigned char cmdstr
[5];
6507 char mhz
[MAXREMSTR
];
6508 char decimals
[MAXREMSTR
];
6512 printf("New frequency: %s\n",newfreq
);
6514 if(split_freq(mhz
, decimals
, newfreq
))
6520 /* The FT-897 likes packed BCD frequencies */
6522 cmdstr
[0] = ((m
/ 100) << 4) + ((m
% 100)/10); /* 100MHz 10Mhz */
6523 cmdstr
[1] = ((m
% 10) << 4) + (d
/ 10000); /* 1MHz 100KHz */
6524 cmdstr
[2] = (((d
% 10000)/1000) << 4) + ((d
% 1000)/ 100); /* 10KHz 1KHz */
6525 cmdstr
[3] = (((d
% 100)/10) << 4) + (d
% 10); /* 100Hz 10Hz */
6526 cmdstr
[4] = 0x01; /* command */
6528 return serial_remote_io(myrpt
, cmdstr
, 5, NULL
, 0, 0);
6532 /* ft-897 simple commands */
6534 static int simple_command_ft897(struct rpt
*myrpt
, char command
)
6536 unsigned char cmdstr
[5];
6538 memset(cmdstr
, 0, 5);
6540 cmdstr
[4] = command
;
6542 return serial_remote_io(myrpt
, cmdstr
, 5, NULL
, 0, 0);
6548 static int set_offset_ft897(struct rpt
*myrpt
, char offset
)
6550 unsigned char cmdstr
[5];
6552 memset(cmdstr
, 0, 5);
6573 return serial_remote_io(myrpt
, cmdstr
, 5, NULL
, 0, 0);
6578 static int set_mode_ft897(struct rpt
*myrpt
, char newmode
)
6580 unsigned char cmdstr
[5];
6582 memset(cmdstr
, 0, 5);
6606 return serial_remote_io(myrpt
, cmdstr
, 5, NULL
, 0, 0);
6609 /* Set tone encode and decode modes */
6611 static int set_ctcss_mode_ft897(struct rpt
*myrpt
, char txplon
, char rxplon
)
6613 unsigned char cmdstr
[5];
6615 memset(cmdstr
, 0, 5);
6617 if(rxplon
&& txplon
)
6618 cmdstr
[0] = 0x2A; /* Encode and Decode */
6619 else if (!rxplon
&& txplon
)
6620 cmdstr
[0] = 0x4A; /* Encode only */
6621 else if (rxplon
&& !txplon
)
6622 cmdstr
[0] = 0x3A; /* Encode only */
6624 cmdstr
[0] = 0x8A; /* OFF */
6628 return serial_remote_io(myrpt
, cmdstr
, 5, NULL
, 0, 0);
6632 /* Set transmit and receive ctcss tone frequencies */
6634 static int set_ctcss_freq_ft897(struct rpt
*myrpt
, char *txtone
, char *rxtone
)
6636 unsigned char cmdstr
[5];
6637 char hertz
[MAXREMSTR
],decimal
[MAXREMSTR
];
6640 memset(cmdstr
, 0, 5);
6642 if(split_ctcss_freq(hertz
, decimal
, txtone
))
6648 cmdstr
[0] = ((h
/ 100) << 4) + (h
% 100)/ 10;
6649 cmdstr
[1] = ((h
% 10) << 4) + (d
% 10);
6653 if(split_ctcss_freq(hertz
, decimal
, rxtone
))
6659 cmdstr
[2] = ((h
/ 100) << 4) + (h
% 100)/ 10;
6660 cmdstr
[3] = ((h
% 10) << 4) + (d
% 10);
6664 return serial_remote_io(myrpt
, cmdstr
, 5, NULL
, 0, 0);
6669 static int set_ft897(struct rpt
*myrpt
)
6674 printf("@@@@ lock on\n");
6676 res
= simple_command_ft897(myrpt
, 0x00); /* LOCK on */
6679 printf("@@@@ ptt off\n");
6682 res
= simple_command_ft897(myrpt
, 0x88); /* PTT off */
6685 printf("Modulation mode\n");
6688 res
= set_mode_ft897(myrpt
, myrpt
->remmode
); /* Modulation mode */
6691 printf("Split off\n");
6694 simple_command_ft897(myrpt
, 0x82); /* Split off */
6697 printf("Frequency\n");
6700 res
= set_freq_ft897(myrpt
, myrpt
->freq
); /* Frequency */
6701 if((myrpt
->remmode
== REM_MODE_FM
)){
6705 res
= set_offset_ft897(myrpt
, myrpt
->offset
); /* Offset if FM */
6706 if((!res
)&&(myrpt
->rxplon
|| myrpt
->txplon
)){
6708 printf("CTCSS tone freqs.\n");
6709 res
= set_ctcss_freq_ft897(myrpt
, myrpt
->txpl
, myrpt
->rxpl
); /* CTCSS freqs if CTCSS is enabled */
6713 printf("CTCSS mode\n");
6714 res
= set_ctcss_mode_ft897(myrpt
, myrpt
->txplon
, myrpt
->rxplon
); /* CTCSS mode */
6717 if((myrpt
->remmode
== REM_MODE_USB
)||(myrpt
->remmode
== REM_MODE_LSB
)){
6719 printf("Clarifier off\n");
6720 simple_command_ft897(myrpt
, 0x85); /* Clarifier off if LSB or USB */
6725 static int closerem_ft897(struct rpt
*myrpt
)
6727 simple_command_ft897(myrpt
, 0x88); /* PTT off */
6732 * Bump frequency up or down by a small amount
6733 * Return 0 if the new frequnecy is valid, or -1 if invalid
6734 * Interval is in Hz, resolution is 10Hz
6737 static int multimode_bump_freq_ft897(struct rpt
*myrpt
, int interval
)
6740 char mhz
[MAXREMSTR
], decimals
[MAXREMSTR
];
6743 printf("Before bump: %s\n", myrpt
->freq
);
6745 if(split_freq(mhz
, decimals
, myrpt
->freq
))
6751 d
+= (interval
/ 10); /* 10Hz resolution */
6756 else if(d
>= 100000){
6761 if(check_freq_ft897(m
, d
, NULL
)){
6763 printf("Bump freq invalid\n");
6767 snprintf(myrpt
->freq
, MAXREMSTR
, "%d.%05d", m
, d
);
6770 printf("After bump: %s\n", myrpt
->freq
);
6772 return set_freq_ft897(myrpt
, myrpt
->freq
);
6778 * IC-706 I/O handlers
6781 /* Check to see that the frequency is valid */
6782 /* Hard coded limits now, configurable later, maybe? */
6785 static int check_freq_ic706(int m
, int d
, int *defmode
)
6787 int dflmd
= REM_MODE_FM
;
6789 if(m
== 1){ /* 160 meters */
6790 dflmd
= REM_MODE_LSB
;
6794 else if(m
== 3){ /* 80 meters */
6795 dflmd
= REM_MODE_LSB
;
6799 else if(m
== 7){ /* 40 meters */
6800 dflmd
= REM_MODE_LSB
;
6804 else if(m
== 14){ /* 20 meters */
6805 dflmd
= REM_MODE_USB
;
6809 else if(m
== 18){ /* 17 meters */
6810 dflmd
= REM_MODE_USB
;
6811 if((d
< 6800) || (d
> 16800))
6814 else if(m
== 21){ /* 15 meters */
6815 dflmd
= REM_MODE_USB
;
6816 if((d
< 20000) || (d
> 45000))
6819 else if(m
== 24){ /* 12 meters */
6820 dflmd
= REM_MODE_USB
;
6821 if((d
< 89000) || (d
> 99000))
6824 else if(m
== 28){ /* 10 meters */
6825 dflmd
= REM_MODE_USB
;
6829 dflmd
= REM_MODE_FM
;
6831 dflmd
= REM_MODE_USB
;
6835 else if(m
== 50){ /* 6 meters */
6837 dflmd
= REM_MODE_FM
;
6839 dflmd
= REM_MODE_USB
;
6842 else if((m
>= 51) && ( m
< 54)){
6843 dflmd
= REM_MODE_FM
;
6845 else if(m
== 144){ /* 2 meters */
6847 dflmd
= REM_MODE_FM
;
6849 dflmd
= REM_MODE_USB
;
6851 else if((m
>= 145) && (m
< 148)){
6852 dflmd
= REM_MODE_FM
;
6854 else if((m
>= 430) && (m
< 450)){ /* 70 centimeters */
6856 dflmd
= REM_MODE_USB
;
6858 dflmd
= REM_MODE_FM
;
6870 /* take a PL frequency and turn it into a code */
6871 static int ic706_pltocode(char *str
)
6876 s
= strchr(str
,'.');
6878 if (s
) i
= atoi(s
+ 1);
6879 i
+= atoi(str
) * 10;
6986 /* ic-706 simple commands */
6988 static int simple_command_ic706(struct rpt
*myrpt
, char command
, char subcommand
)
6990 unsigned char cmdstr
[10];
6992 cmdstr
[0] = cmdstr
[1] = 0xfe;
6993 cmdstr
[2] = myrpt
->p
.civaddr
;
6995 cmdstr
[4] = command
;
6996 cmdstr
[5] = subcommand
;
6999 return(civ_cmd(myrpt
,cmdstr
,7));
7003 * Set a new frequency for the ic706
7006 static int set_freq_ic706(struct rpt
*myrpt
, char *newfreq
)
7008 unsigned char cmdstr
[20];
7009 char mhz
[MAXREMSTR
], decimals
[MAXREMSTR
];
7014 printf("New frequency: %s\n",newfreq
);
7016 if(split_freq(mhz
, decimals
, newfreq
))
7022 /* The ic-706 likes packed BCD frequencies */
7024 cmdstr
[0] = cmdstr
[1] = 0xfe;
7025 cmdstr
[2] = myrpt
->p
.civaddr
;
7028 cmdstr
[5] = ((d
% 10) << 4);
7029 cmdstr
[6] = (((d
% 1000)/ 100) << 4) + ((d
% 100)/10);
7030 cmdstr
[7] = ((d
/ 10000) << 4) + ((d
% 10000)/1000);
7031 cmdstr
[8] = (((m
% 100)/10) << 4) + (m
% 10);
7032 cmdstr
[9] = (m
/ 100);
7035 return(civ_cmd(myrpt
,cmdstr
,11));
7040 static int set_offset_ic706(struct rpt
*myrpt
, char offset
)
7061 return simple_command_ic706(myrpt
,0x0f,c
);
7067 static int set_mode_ic706(struct rpt
*myrpt
, char newmode
)
7091 return simple_command_ic706(myrpt
,6,c
);
7094 /* Set tone encode and decode modes */
7096 static int set_ctcss_mode_ic706(struct rpt
*myrpt
, char txplon
, char rxplon
)
7098 unsigned char cmdstr
[10];
7101 cmdstr
[0] = cmdstr
[1] = 0xfe;
7102 cmdstr
[2] = myrpt
->p
.civaddr
;
7106 cmdstr
[6] = (txplon
!= 0);
7109 rv
= civ_cmd(myrpt
,cmdstr
,8);
7112 cmdstr
[0] = cmdstr
[1] = 0xfe;
7113 cmdstr
[2] = myrpt
->p
.civaddr
;
7117 cmdstr
[6] = (rxplon
!= 0);
7120 return(civ_cmd(myrpt
,cmdstr
,8));
7124 /* Set transmit and receive ctcss tone frequencies */
7126 static int set_ctcss_freq_ic706(struct rpt
*myrpt
, char *txtone
, char *rxtone
)
7128 unsigned char cmdstr
[10];
7129 char hertz
[MAXREMSTR
],decimal
[MAXREMSTR
];
7132 memset(cmdstr
, 0, 5);
7134 if(split_ctcss_freq(hertz
, decimal
, txtone
))
7140 cmdstr
[0] = cmdstr
[1] = 0xfe;
7141 cmdstr
[2] = myrpt
->p
.civaddr
;
7145 cmdstr
[6] = ((h
/ 100) << 4) + (h
% 100)/ 10;
7146 cmdstr
[7] = ((h
% 10) << 4) + (d
% 10);
7149 rv
= civ_cmd(myrpt
,cmdstr
,9);
7152 if (!rxtone
) return(0);
7154 if(split_ctcss_freq(hertz
, decimal
, rxtone
))
7160 cmdstr
[0] = cmdstr
[1] = 0xfe;
7161 cmdstr
[2] = myrpt
->p
.civaddr
;
7165 cmdstr
[6] = ((h
/ 100) << 4) + (h
% 100)/ 10;
7166 cmdstr
[7] = ((h
% 10) << 4) + (d
% 10);
7168 return(civ_cmd(myrpt
,cmdstr
,9));
7172 static int vfo_ic706(struct rpt
*myrpt
)
7174 unsigned char cmdstr
[10];
7176 cmdstr
[0] = cmdstr
[1] = 0xfe;
7177 cmdstr
[2] = myrpt
->p
.civaddr
;
7182 return(civ_cmd(myrpt
,cmdstr
,6));
7185 static int mem2vfo_ic706(struct rpt
*myrpt
)
7187 unsigned char cmdstr
[10];
7189 cmdstr
[0] = cmdstr
[1] = 0xfe;
7190 cmdstr
[2] = myrpt
->p
.civaddr
;
7195 return(civ_cmd(myrpt
,cmdstr
,6));
7198 static int select_mem_ic706(struct rpt
*myrpt
, int slot
)
7200 unsigned char cmdstr
[10];
7202 cmdstr
[0] = cmdstr
[1] = 0xfe;
7203 cmdstr
[2] = myrpt
->p
.civaddr
;
7207 cmdstr
[6] = ((slot
/ 10) << 4) + (slot
% 10);
7210 return(civ_cmd(myrpt
,cmdstr
,8));
7213 static int set_ic706(struct rpt
*myrpt
)
7218 printf("Set to VFO A\n");
7221 res
= simple_command_ic706(myrpt
,7,0);
7224 if((myrpt
->remmode
== REM_MODE_FM
))
7226 i
= ic706_pltocode(myrpt
->rxpl
);
7227 if (i
== -1) return -1;
7229 printf("Select memory number\n");
7231 res
= select_mem_ic706(myrpt
,i
+ IC706_PL_MEMORY_OFFSET
);
7233 printf("Transfer memory to VFO\n");
7235 res
= mem2vfo_ic706(myrpt
);
7239 printf("Set to VFO\n");
7242 res
= vfo_ic706(myrpt
);
7245 printf("Modulation mode\n");
7248 res
= set_mode_ic706(myrpt
, myrpt
->remmode
); /* Modulation mode */
7251 printf("Split off\n");
7254 simple_command_ic706(myrpt
, 0x82,0); /* Split off */
7257 printf("Frequency\n");
7260 res
= set_freq_ic706(myrpt
, myrpt
->freq
); /* Frequency */
7261 if((myrpt
->remmode
== REM_MODE_FM
)){
7265 res
= set_offset_ic706(myrpt
, myrpt
->offset
); /* Offset if FM */
7268 printf("CTCSS mode\n");
7269 res
= set_ctcss_mode_ic706(myrpt
, myrpt
->txplon
, myrpt
->rxplon
); /* CTCSS mode */
7276 * Bump frequency up or down by a small amount
7277 * Return 0 if the new frequnecy is valid, or -1 if invalid
7278 * Interval is in Hz, resolution is 10Hz
7281 static int multimode_bump_freq_ic706(struct rpt
*myrpt
, int interval
)
7284 char mhz
[MAXREMSTR
], decimals
[MAXREMSTR
];
7285 unsigned char cmdstr
[20];
7288 printf("Before bump: %s\n", myrpt
->freq
);
7290 if(split_freq(mhz
, decimals
, myrpt
->freq
))
7296 d
+= (interval
/ 10); /* 10Hz resolution */
7301 else if(d
>= 100000){
7306 if(check_freq_ic706(m
, d
, NULL
)){
7308 printf("Bump freq invalid\n");
7312 snprintf(myrpt
->freq
, MAXREMSTR
, "%d.%05d", m
, d
);
7315 printf("After bump: %s\n", myrpt
->freq
);
7317 /* The ic-706 likes packed BCD frequencies */
7319 cmdstr
[0] = cmdstr
[1] = 0xfe;
7320 cmdstr
[2] = myrpt
->p
.civaddr
;
7323 cmdstr
[5] = ((d
% 10) << 4);
7324 cmdstr
[6] = (((d
% 1000)/ 100) << 4) + ((d
% 100)/10);
7325 cmdstr
[7] = ((d
/ 10000) << 4) + ((d
% 10000)/1000);
7326 cmdstr
[8] = (((m
% 100)/10) << 4) + (m
% 10);
7327 cmdstr
[9] = (m
/ 100);
7330 return(serial_remote_io(myrpt
,cmdstr
,11,NULL
,0,0));
7336 * Dispatch to correct I/O handler
7339 static int setrem(struct rpt
*myrpt
)
7342 char *offsets
[] = {"MINUS","SIMPLEX","PLUS"};
7343 char *powerlevels
[] = {"LOW","MEDIUM","HIGH"};
7344 char *modes
[] = {"FM","USB","LSB","AM"};
7347 if (myrpt
->p
.archivedir
)
7349 sprintf(str
,"FREQ,%s,%s,%s,%s,%s,%s,%d,%d",myrpt
->freq
,
7350 modes
[(int)myrpt
->remmode
],
7351 myrpt
->txpl
,myrpt
->rxpl
,offsets
[(int)myrpt
->offset
],
7352 powerlevels
[(int)myrpt
->powerlevel
],myrpt
->txplon
,
7354 donodelog(myrpt
,str
);
7356 if(!strcmp(myrpt
->remote
, remote_rig_ft897
))
7358 rpt_telemetry(myrpt
,SETREMOTE
,NULL
);
7361 if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
7363 rpt_telemetry(myrpt
,SETREMOTE
,NULL
);
7366 else if(!strcmp(myrpt
->remote
, remote_rig_rbi
))
7368 res
= setrbi_check(myrpt
);
7371 rpt_telemetry(myrpt
,SETREMOTE
,NULL
);
7375 else if(!strcmp(myrpt
->remote
, remote_rig_kenwood
)) {
7376 rpt_telemetry(myrpt
,SETREMOTE
,NULL
);
7382 if (res
< 0) ast_log(LOG_ERROR
,"Unable to send remote command on node %s\n",myrpt
->name
);
7387 static int closerem(struct rpt
*myrpt
)
7389 if(!strcmp(myrpt
->remote
, remote_rig_ft897
))
7390 return closerem_ft897(myrpt
);
7396 * Dispatch to correct RX frequency checker
7399 static int check_freq(struct rpt
*myrpt
, int m
, int d
, int *defmode
)
7401 if(!strcmp(myrpt
->remote
, remote_rig_ft897
))
7402 return check_freq_ft897(m
, d
, defmode
);
7403 else if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
7404 return check_freq_ic706(m
, d
, defmode
);
7405 else if(!strcmp(myrpt
->remote
, remote_rig_rbi
))
7406 return check_freq_rbi(m
, d
, defmode
);
7407 else if(!strcmp(myrpt
->remote
, remote_rig_kenwood
))
7408 return check_freq_kenwood(m
, d
, defmode
);
7414 * Check TX frequency before transmitting
7417 static char check_tx_freq(struct rpt
*myrpt
)
7420 int radio_mhz
, radio_decimals
, ulimit_mhz
, ulimit_decimals
, llimit_mhz
, llimit_decimals
;
7421 char radio_mhz_char
[MAXREMSTR
];
7422 char radio_decimals_char
[MAXREMSTR
];
7423 char limit_mhz_char
[MAXREMSTR
];
7424 char limit_decimals_char
[MAXREMSTR
];
7426 char *limit_ranges
[40];
7427 struct ast_variable
*limitlist
;
7430 /* Must have user logged in and tx_limits defined */
7432 if(!myrpt
->p
.txlimitsstanzaname
|| !myrpt
->loginuser
[0] || !myrpt
->loginlevel
[0]){
7434 ast_log(LOG_NOTICE
, "No tx band table defined, or no user logged in\n");
7436 return 1; /* Assume it's ok otherwise */
7439 /* Retrieve the band table for the loginlevel */
7440 limitlist
= ast_variable_browse(myrpt
->cfg
, myrpt
->p
.txlimitsstanzaname
);
7443 ast_log(LOG_WARNING
, "No entries in %s band table stanza\n", myrpt
->p
.txlimitsstanzaname
);
7447 split_freq(radio_mhz_char
, radio_decimals_char
, myrpt
->freq
);
7448 radio_mhz
= atoi(radio_mhz_char
);
7449 radio_decimals
= decimals2int(radio_decimals_char
);
7453 ast_log(LOG_NOTICE
, "Login User = %s, login level = %s\n", myrpt
->loginuser
, myrpt
->loginlevel
);
7456 /* Find our entry */
7458 for(;limitlist
; limitlist
=limitlist
->next
){
7459 if(!strcmp(limitlist
->name
, myrpt
->loginlevel
))
7464 ast_log(LOG_WARNING
, "Can't find %s entry in band table stanza %s\n", myrpt
->loginlevel
, myrpt
->p
.txlimitsstanzaname
);
7469 ast_log(LOG_NOTICE
, "Auth %s = %s\n", limitlist
->name
, limitlist
->value
);
7472 /* Parse the limits */
7474 strncpy(limits
, limitlist
->value
, 256);
7476 finddelim(limits
, limit_ranges
, 40);
7477 for(i
= 0; i
< 40 && limit_ranges
[i
] ; i
++){
7480 strncpy(range
, limit_ranges
[i
], 40);
7483 ast_log(LOG_NOTICE
, "Checking to see if %s is within limits of %s\n", myrpt
->freq
, range
);
7486 r
= strchr(range
, '-');
7488 ast_log(LOG_WARNING
, "Malformed range in %s tx band table entry\n", limitlist
->name
);
7492 s
= eatwhite(range
);
7494 split_freq(limit_mhz_char
, limit_decimals_char
, s
);
7495 llimit_mhz
= atoi(limit_mhz_char
);
7496 llimit_decimals
= decimals2int(limit_decimals_char
);
7497 split_freq(limit_mhz_char
, limit_decimals_char
, r
);
7498 ulimit_mhz
= atoi(limit_mhz_char
);
7499 ulimit_decimals
= decimals2int(limit_decimals_char
);
7501 if((radio_mhz
>= llimit_mhz
) && (radio_mhz
<= ulimit_mhz
)){
7502 if(radio_mhz
== llimit_mhz
){ /* CASE 1: TX freq is in llimit mhz portion of band */
7503 if(radio_decimals
>= llimit_decimals
){ /* Cannot be below llimit decimals */
7504 if(llimit_mhz
== ulimit_mhz
){ /* If bandwidth < 1Mhz, check ulimit decimals */
7505 if(radio_decimals
<= ulimit_decimals
){
7510 ast_log(LOG_NOTICE
, "Invalid TX frequency, debug msg 1\n");
7518 else{ /* Is below llimit decimals */
7520 ast_log(LOG_NOTICE
, "Invalid TX frequency, debug msg 2\n");
7524 else if(radio_mhz
== ulimit_mhz
){ /* CASE 2: TX freq not in llimit mhz portion of band */
7525 if(radio_decimals
<= ulimit_decimals
){
7528 else{ /* Is above ulimit decimals */
7530 ast_log(LOG_NOTICE
, "Invalid TX frequency, debug msg 3\n");
7534 else /* CASE 3: TX freq within a multi-Mhz band and ok */
7538 if(debug
> 3) /* No match found in TX band table */
7539 ast_log(LOG_NOTICE
, "Invalid TX frequency, debug msg 4\n");
7545 * Dispatch to correct frequency bumping function
7548 static int multimode_bump_freq(struct rpt
*myrpt
, int interval
)
7550 if(!strcmp(myrpt
->remote
, remote_rig_ft897
))
7551 return multimode_bump_freq_ft897(myrpt
, interval
);
7552 else if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
7553 return multimode_bump_freq_ic706(myrpt
, interval
);
7560 * Queue announcment that scan has been stopped
7563 static void stop_scan(struct rpt
*myrpt
)
7565 myrpt
->hfscanstop
= 1;
7566 rpt_telemetry(myrpt
,SCAN
,0);
7570 * This is called periodically when in scan mode
7574 static int service_scan(struct rpt
*myrpt
)
7577 char mhz
[MAXREMSTR
], decimals
[MAXREMSTR
], k10
=0i
, k100
=0;
7579 switch(myrpt
->hfscanmode
){
7581 case HF_SCAN_DOWN_SLOW
:
7582 interval
= -10; /* 100Hz /sec */
7585 case HF_SCAN_DOWN_QUICK
:
7586 interval
= -50; /* 500Hz /sec */
7589 case HF_SCAN_DOWN_FAST
:
7590 interval
= -200; /* 2KHz /sec */
7593 case HF_SCAN_UP_SLOW
:
7594 interval
= 10; /* 100Hz /sec */
7597 case HF_SCAN_UP_QUICK
:
7598 interval
= 50; /* 500 Hz/sec */
7601 case HF_SCAN_UP_FAST
:
7602 interval
= 200; /* 2KHz /sec */
7606 myrpt
->hfscanmode
= 0; /* Huh? */
7610 res
= split_freq(mhz
, decimals
, myrpt
->freq
);
7615 res
= multimode_bump_freq(myrpt
, interval
);
7619 res
= split_freq(mhz
, decimals
, myrpt
->freq
);
7623 myrpt
->hfscanmode
= 0;
7624 myrpt
->hfscanstatus
= -2;
7628 /* Announce 10KHz boundaries */
7629 if(k10
!= decimals
[1]){
7630 int myhund
= (interval
< 0) ? k100
: decimals
[0];
7631 int myten
= (interval
< 0) ? k10
: decimals
[1];
7632 myrpt
->hfscanstatus
= (myten
== '0') ? (myhund
- '0') * 100 : (myten
- '0') * 10;
7633 } else myrpt
->hfscanstatus
= 0;
7639 * Retrieve a memory channel
7640 * Return 0 if sucessful,
7641 * -1 if channel not found,
7645 static int retreive_memory(struct rpt
*myrpt
, char *memory
)
7647 char tmp
[30], *s
, *s1
, *val
;
7649 val
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->p
.memory
, memory
);
7653 strncpy(tmp
,val
,sizeof(tmp
) - 1);
7654 tmp
[sizeof(tmp
)-1] = 0;
7656 s
= strchr(tmp
,',');
7664 strncpy(myrpt
->freq
, tmp
, sizeof(myrpt
->freq
) - 1);
7665 strncpy(myrpt
->rxpl
, s
, sizeof(myrpt
->rxpl
) - 1);
7666 strncpy(myrpt
->txpl
, s
, sizeof(myrpt
->rxpl
) - 1);
7667 myrpt
->remmode
= REM_MODE_FM
;
7668 myrpt
->offset
= REM_SIMPLEX
;
7669 myrpt
->powerlevel
= REM_MEDPWR
;
7670 myrpt
->txplon
= myrpt
->rxplon
= 0;
7675 strcpy(myrpt
->rxpl
, "100.0");
7676 strcpy(myrpt
->txpl
, "100.0");
7677 myrpt
->remmode
= REM_MODE_AM
;
7681 strcpy(myrpt
->rxpl
, "100.0");
7682 strcpy(myrpt
->txpl
, "100.0");
7683 myrpt
->remmode
= REM_MODE_LSB
;
7686 myrpt
->remmode
= REM_MODE_FM
;
7690 myrpt
->powerlevel
= REM_LOWPWR
;
7694 myrpt
->powerlevel
= REM_HIPWR
;
7699 myrpt
->powerlevel
= REM_MEDPWR
;
7703 myrpt
->offset
= REM_MINUS
;
7707 myrpt
->offset
= REM_PLUS
;
7712 myrpt
->offset
= REM_SIMPLEX
;
7727 strcpy(myrpt
->rxpl
, "100.0");
7728 strcpy(myrpt
->txpl
, "100.0");
7729 myrpt
->remmode
= REM_MODE_USB
;
7741 * Remote base function
7744 static int function_remote(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
7747 int i
,j
,p
,r
,ht
,k
,l
,ls2
,m
,d
,offset
,offsave
, modesave
, defmode
;
7749 char oc
,*cp
,*cp1
,*cp2
;
7750 char tmp
[20], freq
[20] = "", savestr
[20] = "";
7751 char mhz
[MAXREMSTR
], decimals
[MAXREMSTR
];
7753 if((!param
) || (command_source
== SOURCE_RPT
) || (command_source
== SOURCE_LNK
))
7758 if ((p
!= 99) && (p
!= 5) && (p
!= 140) && myrpt
->p
.authlevel
&&
7759 (!myrpt
->loginlevel
[0])) return DC_ERROR
;
7760 multimode
= multimode_capable(myrpt
);
7764 case 1: /* retrieve memory */
7765 if(strlen(digitbuf
) < 2) /* needs 2 digits */
7768 for(i
= 0 ; i
< 2 ; i
++){
7769 if((digitbuf
[i
] < '0') || (digitbuf
[i
] > '9'))
7773 r
= retreive_memory(myrpt
, digitbuf
);
7775 rpt_telemetry(myrpt
,MEMNOTFOUND
,NULL
);
7781 if (setrem(myrpt
) == -1) return DC_ERROR
;
7784 case 2: /* set freq and offset */
7787 for(i
= 0, j
= 0, k
= 0, l
= 0 ; digitbuf
[i
] ; i
++){ /* look for M+*K+*O or M+*H+* depending on mode */
7788 if(digitbuf
[i
] == '*'){
7792 if((digitbuf
[i
] < '0') || (digitbuf
[i
] > '9'))
7796 l
++; /* # of digits before first * */
7798 k
++; /* # of digits after first * */
7802 i
= strlen(digitbuf
) - 1;
7804 if((j
> 2) || (l
> 3) || (k
> 6))
7805 goto invalid_freq
; /* &^@#! */
7808 if((j
> 2) || (l
> 4) || (k
> 3))
7809 goto invalid_freq
; /* &^@#! */
7812 /* Wait for M+*K+* */
7815 break; /* Not yet */
7817 /* We have a frequency */
7819 strncpy(tmp
, digitbuf
,sizeof(tmp
) - 1);
7822 s1
= strsep(&s
, "*"); /* Pick off MHz */
7823 s2
= strsep(&s
,"*"); /* Pick off KHz and Hz */
7826 switch(ls2
){ /* Allow partial entry of khz and hz digits for laziness support */
7839 if((s2
[2] != '0')&&(s2
[2] != '5'))
7847 ht
= 10 * (atoi(s2
+(ls2
-1)));
7852 ht
= (atoi(s2
+(ls2
-2)));
7859 /* Check frequency for validity and establish a default mode */
7861 snprintf(freq
, sizeof(freq
), "%s.%03d%02d",s1
, k
, ht
);
7864 printf("New frequency: %s\n", freq
);
7866 split_freq(mhz
, decimals
, freq
);
7870 if(check_freq(myrpt
, m
, d
, &defmode
)) /* Check to see if frequency entered is legit */
7874 if((defmode
== REM_MODE_FM
) && (digitbuf
[i
] == '*')) /* If FM, user must enter and additional offset digit */
7875 break; /* Not yet */
7878 offset
= REM_SIMPLEX
; /* Assume simplex */
7880 if(defmode
== REM_MODE_FM
){
7881 oc
= *s
; /* Pick off offset */
7890 offset
= REM_SIMPLEX
;
7902 offsave
= myrpt
->offset
;
7903 modesave
= myrpt
->remmode
;
7904 strncpy(savestr
, myrpt
->freq
, sizeof(savestr
) - 1);
7905 strncpy(myrpt
->freq
, freq
, sizeof(myrpt
->freq
) - 1);
7906 myrpt
->offset
= offset
;
7907 myrpt
->remmode
= defmode
;
7909 if (setrem(myrpt
) == -1){
7910 myrpt
->offset
= offsave
;
7911 myrpt
->remmode
= modesave
;
7912 strncpy(myrpt
->freq
, savestr
, sizeof(myrpt
->freq
) - 1);
7919 rpt_telemetry(myrpt
,INVFREQ
,NULL
);
7922 case 3: /* set rx PL tone */
7923 for(i
= 0, j
= 0, k
= 0, l
= 0 ; digitbuf
[i
] ; i
++){ /* look for N+*N */
7924 if(digitbuf
[i
] == '*'){
7928 if((digitbuf
[i
] < '0') || (digitbuf
[i
] > '9'))
7937 if((j
> 1) || (k
> 3) || (l
> 1))
7938 return DC_ERROR
; /* &$@^! */
7939 i
= strlen(digitbuf
) - 1;
7940 if((j
!= 1) || (k
< 2)|| (l
!= 1))
7941 break; /* Not yet */
7943 printf("PL digits entered %s\n", digitbuf
);
7945 strncpy(tmp
, digitbuf
, sizeof(tmp
) - 1);
7946 /* see if we have at least 1 */
7947 s
= strchr(tmp
,'*');
7950 strncpy(savestr
, myrpt
->rxpl
, sizeof(savestr
) - 1);
7951 strncpy(myrpt
->rxpl
, tmp
, sizeof(myrpt
->rxpl
) - 1);
7952 if(!strcmp(myrpt
->remote
, remote_rig_rbi
))
7954 strncpy(myrpt
->txpl
, tmp
, sizeof(myrpt
->txpl
) - 1);
7956 if (setrem(myrpt
) == -1){
7957 strncpy(myrpt
->rxpl
, savestr
, sizeof(myrpt
->rxpl
) - 1);
7964 case 4: /* set tx PL tone */
7965 /* cant set tx tone on RBI (rx tone does both) */
7966 if(!strcmp(myrpt
->remote
, remote_rig_rbi
))
7968 if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
7970 for(i
= 0, j
= 0, k
= 0, l
= 0 ; digitbuf
[i
] ; i
++){ /* look for N+*N */
7971 if(digitbuf
[i
] == '*'){
7975 if((digitbuf
[i
] < '0') || (digitbuf
[i
] > '9'))
7984 if((j
> 1) || (k
> 3) || (l
> 1))
7985 return DC_ERROR
; /* &$@^! */
7986 i
= strlen(digitbuf
) - 1;
7987 if((j
!= 1) || (k
< 2)|| (l
!= 1))
7988 break; /* Not yet */
7990 printf("PL digits entered %s\n", digitbuf
);
7992 strncpy(tmp
, digitbuf
, sizeof(tmp
) - 1);
7993 /* see if we have at least 1 */
7994 s
= strchr(tmp
,'*');
7997 strncpy(savestr
, myrpt
->txpl
, sizeof(savestr
) - 1);
7998 strncpy(myrpt
->txpl
, tmp
, sizeof(myrpt
->txpl
) - 1);
8000 if (setrem(myrpt
) == -1){
8001 strncpy(myrpt
->txpl
, savestr
, sizeof(myrpt
->txpl
) - 1);
8009 case 6: /* MODE (FM,USB,LSB,AM) */
8010 if(strlen(digitbuf
) < 1)
8014 return DC_ERROR
; /* Multimode radios only */
8018 split_freq(mhz
, decimals
, myrpt
->freq
);
8020 if(m
< 29) /* No FM allowed below 29MHz! */
8022 myrpt
->remmode
= REM_MODE_FM
;
8024 rpt_telemetry(myrpt
,REMMODE
,NULL
);
8028 myrpt
->remmode
= REM_MODE_USB
;
8029 rpt_telemetry(myrpt
,REMMODE
,NULL
);
8033 myrpt
->remmode
= REM_MODE_LSB
;
8034 rpt_telemetry(myrpt
,REMMODE
,NULL
);
8038 myrpt
->remmode
= REM_MODE_AM
;
8039 rpt_telemetry(myrpt
,REMMODE
,NULL
);
8048 return DC_COMPLETEQUIET
;
8050 /* cant log in when logged in */
8051 if (myrpt
->loginlevel
[0])
8053 *myrpt
->loginuser
= 0;
8054 myrpt
->loginlevel
[0] = 0;
8056 cp1
= strchr(cp
,',');
8057 ast_mutex_lock(&myrpt
->lock
);
8061 cp2
= strchr(cp1
+ 1,',');
8065 strncpy(myrpt
->loginlevel
,cp2
+ 1,
8066 sizeof(myrpt
->loginlevel
) - 1);
8068 strncpy(myrpt
->loginuser
,cp1
+ 1,sizeof(myrpt
->loginuser
));
8069 ast_mutex_unlock(&myrpt
->lock
);
8070 if (myrpt
->p
.archivedir
)
8074 sprintf(str
,"LOGIN,%s,%s",
8075 myrpt
->loginuser
,myrpt
->loginlevel
);
8076 donodelog(myrpt
,str
);
8079 printf("loginuser %s level %s\n",myrpt
->loginuser
,myrpt
->loginlevel
);
8080 rpt_telemetry(myrpt
,REMLOGIN
,NULL
);
8083 return DC_COMPLETEQUIET
;
8084 case 100: /* RX PL Off */
8087 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8088 return DC_COMPLETEQUIET
;
8089 case 101: /* RX PL On */
8092 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8093 return DC_COMPLETEQUIET
;
8094 case 102: /* TX PL Off */
8097 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8098 return DC_COMPLETEQUIET
;
8099 case 103: /* TX PL On */
8102 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8103 return DC_COMPLETEQUIET
;
8104 case 104: /* Low Power */
8105 if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
8107 myrpt
->powerlevel
= REM_LOWPWR
;
8109 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8110 return DC_COMPLETEQUIET
;
8111 case 105: /* Medium Power */
8112 if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
8114 myrpt
->powerlevel
= REM_MEDPWR
;
8116 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8117 return DC_COMPLETEQUIET
;
8118 case 106: /* Hi Power */
8119 if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
8121 myrpt
->powerlevel
= REM_HIPWR
;
8123 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8124 return DC_COMPLETEQUIET
;
8125 case 107: /* Bump down 20Hz */
8126 multimode_bump_freq(myrpt
, -20);
8128 case 108: /* Bump down 100Hz */
8129 multimode_bump_freq(myrpt
, -100);
8131 case 109: /* Bump down 500Hz */
8132 multimode_bump_freq(myrpt
, -500);
8134 case 110: /* Bump up 20Hz */
8135 multimode_bump_freq(myrpt
, 20);
8137 case 111: /* Bump up 100Hz */
8138 multimode_bump_freq(myrpt
, 100);
8140 case 112: /* Bump up 500Hz */
8141 multimode_bump_freq(myrpt
, 500);
8143 case 113: /* Scan down slow */
8144 myrpt
->scantimer
= REM_SCANTIME
;
8145 myrpt
->hfscanmode
= HF_SCAN_DOWN_SLOW
;
8146 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8147 return DC_COMPLETEQUIET
;
8148 case 114: /* Scan down quick */
8149 myrpt
->scantimer
= REM_SCANTIME
;
8150 myrpt
->hfscanmode
= HF_SCAN_DOWN_QUICK
;
8151 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8152 return DC_COMPLETEQUIET
;
8153 case 115: /* Scan down fast */
8154 myrpt
->scantimer
= REM_SCANTIME
;
8155 myrpt
->hfscanmode
= HF_SCAN_DOWN_FAST
;
8156 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8157 return DC_COMPLETEQUIET
;
8158 case 116: /* Scan up slow */
8159 myrpt
->scantimer
= REM_SCANTIME
;
8160 myrpt
->hfscanmode
= HF_SCAN_UP_SLOW
;
8161 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8162 return DC_COMPLETEQUIET
;
8163 case 117: /* Scan up quick */
8164 myrpt
->scantimer
= REM_SCANTIME
;
8165 myrpt
->hfscanmode
= HF_SCAN_UP_QUICK
;
8166 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8167 return DC_COMPLETEQUIET
;
8168 case 118: /* Scan up fast */
8169 myrpt
->scantimer
= REM_SCANTIME
;
8170 myrpt
->hfscanmode
= HF_SCAN_UP_FAST
;
8171 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
8172 return DC_COMPLETEQUIET
;
8173 case 119: /* Tune Request */
8174 /* if not currently going, and valid to do */
8175 if((!myrpt
->tunerequest
) &&
8176 ((!strcmp(myrpt
->remote
, remote_rig_ft897
) ||
8177 !strcmp(myrpt
->remote
, remote_rig_ic706
)) )) {
8178 myrpt
->remotetx
= 0;
8179 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_UNKEY
);
8180 myrpt
->tunerequest
= 1;
8181 rpt_telemetry(myrpt
,TUNE
,NULL
);
8182 return DC_COMPLETEQUIET
;
8185 case 5: /* Long Status */
8186 rpt_telemetry(myrpt
,REMLONGSTATUS
,NULL
);
8187 return DC_COMPLETEQUIET
;
8188 case 140: /* Short Status */
8189 rpt_telemetry(myrpt
,REMSHORTSTATUS
,NULL
);
8190 return DC_COMPLETEQUIET
;
8207 do_dtmf_local(myrpt
,remdtmfstr
[p
- 200]);
8208 return DC_COMPLETEQUIET
;
8212 return DC_INDETERMINATE
;
8216 static int handle_remote_dtmf_digit(struct rpt
*myrpt
,char c
, char *keyed
, int phonemode
)
8219 int ret
,res
= 0,src
;
8221 time(&myrpt
->last_activity_time
);
8222 /* Stop scan mode if in scan mode */
8223 if(myrpt
->hfscanmode
){
8230 if ((myrpt
->dtmf_time_rem
+ DTMF_TIMEOUT
) < now
)
8232 myrpt
->dtmfidx
= -1;
8233 myrpt
->dtmfbuf
[0] = 0;
8234 myrpt
->dtmf_time_rem
= 0;
8236 /* if decode not active */
8237 if (myrpt
->dtmfidx
== -1)
8239 /* if not lead-in digit, dont worry */
8240 if (c
!= myrpt
->p
.funcchar
)
8242 if (!myrpt
->p
.propagate_dtmf
)
8244 rpt_mutex_lock(&myrpt
->lock
);
8245 do_dtmf_local(myrpt
,c
);
8246 rpt_mutex_unlock(&myrpt
->lock
);
8251 myrpt
->dtmfbuf
[0] = 0;
8252 myrpt
->dtmf_time_rem
= now
;
8255 /* if too many in buffer, start over */
8256 if (myrpt
->dtmfidx
>= MAXDTMF
)
8259 myrpt
->dtmfbuf
[0] = 0;
8260 myrpt
->dtmf_time_rem
= now
;
8262 if (c
== myrpt
->p
.funcchar
)
8264 /* if star at beginning, or 2 together, erase buffer */
8265 if ((myrpt
->dtmfidx
< 1) ||
8266 (myrpt
->dtmfbuf
[myrpt
->dtmfidx
- 1] == myrpt
->p
.funcchar
))
8269 myrpt
->dtmfbuf
[0] = 0;
8270 myrpt
->dtmf_time_rem
= now
;
8274 myrpt
->dtmfbuf
[myrpt
->dtmfidx
++] = c
;
8275 myrpt
->dtmfbuf
[myrpt
->dtmfidx
] = 0;
8276 myrpt
->dtmf_time_rem
= now
;
8280 if (phonemode
> 1) src
= SOURCE_DPHONE
;
8281 else if (phonemode
) src
= SOURCE_PHONE
;
8282 ret
= collect_function_digits(myrpt
, myrpt
->dtmfbuf
, src
, NULL
);
8286 case DC_INDETERMINATE
:
8291 if (keyed
) *keyed
= 1;
8297 myrpt
->dtmfbuf
[0] = 0;
8304 case DC_COMPLETEQUIET
:
8305 myrpt
->totalexecdcommands
++;
8306 myrpt
->dailyexecdcommands
++;
8307 strncpy(myrpt
->lastdtmfcommand
, myrpt
->dtmfbuf
, MAXDTMF
-1);
8308 myrpt
->lastdtmfcommand
[MAXDTMF
-1] = '\0';
8309 myrpt
->dtmfbuf
[0] = 0;
8310 myrpt
->dtmfidx
= -1;
8311 myrpt
->dtmf_time_rem
= 0;
8316 myrpt
->dtmfbuf
[0] = 0;
8317 myrpt
->dtmfidx
= -1;
8318 myrpt
->dtmf_time_rem
= 0;
8326 static int handle_remote_data(struct rpt
*myrpt
, char *str
)
8328 char tmp
[300],cmd
[300],dest
[300],src
[300],c
;
8331 /* put string in our buffer */
8332 strncpy(tmp
,str
,sizeof(tmp
) - 1);
8333 if (!strcmp(tmp
,discstr
)) return 0;
8335 #ifndef DO_NOT_NOTIFY_MDC1200_ON_REMOTE_BASES
8338 if (sscanf(tmp
,"%s %s %x",cmd
,src
,&seq
) != 3)
8340 ast_log(LOG_WARNING
, "Unable to parse ident string %s\n",str
);
8343 mdc1200_notify(myrpt
,src
,seq
);
8347 if (sscanf(tmp
,"%s %s %s %d %c",cmd
,dest
,src
,&seq
,&c
) != 5)
8349 ast_log(LOG_WARNING
, "Unable to parse link string %s\n",str
);
8352 if (strcmp(cmd
,"D"))
8354 ast_log(LOG_WARNING
, "Unable to parse link string %s\n",str
);
8357 /* if not for me, ignore */
8358 if (strcmp(dest
,myrpt
->name
)) return 0;
8359 if (myrpt
->p
.archivedir
)
8363 sprintf(str
,"DTMF,%c",c
);
8364 donodelog(myrpt
,str
);
8366 c
= func_xlat(myrpt
,c
,&myrpt
->p
.outxlat
);
8368 res
= handle_remote_dtmf_digit(myrpt
,c
, NULL
, 0);
8371 rpt_telemetry(myrpt
,COMPLETE
,NULL
);
8375 static int handle_remote_phone_dtmf(struct rpt
*myrpt
, char c
, char *keyed
, int phonemode
)
8380 if (keyed
&& *keyed
&& (c
== myrpt
->p
.endchar
))
8383 return DC_INDETERMINATE
;
8386 if (myrpt
->p
.archivedir
)
8390 sprintf(str
,"DTMF(P),%c",c
);
8391 donodelog(myrpt
,str
);
8393 res
= handle_remote_dtmf_digit(myrpt
,c
,keyed
, phonemode
);
8396 rpt_telemetry(myrpt
,COMPLETE
,NULL
);
8400 static int attempt_reconnect(struct rpt
*myrpt
, struct rpt_link
*l
)
8402 char *val
, *s
, *s1
, *s2
, *tele
;
8403 char tmp
[300], deststr
[300] = "";
8405 val
= node_lookup(myrpt
,l
->name
);
8408 fprintf(stderr
,"attempt_reconnect: cannot find node %s\n",l
->name
);
8412 rpt_mutex_lock(&myrpt
->lock
);
8413 /* remove from queue */
8414 remque((struct qelem
*) l
);
8415 rpt_mutex_unlock(&myrpt
->lock
);
8416 strncpy(tmp
,val
,sizeof(tmp
) - 1);
8418 s1
= strsep(&s
,",");
8419 s2
= strsep(&s
,",");
8420 snprintf(deststr
, sizeof(deststr
), "IAX2/%s", s1
);
8421 tele
= strchr(deststr
, '/');
8423 fprintf(stderr
,"attempt_reconnect:Dial number (%s) must be in format tech/number\n",deststr
);
8429 l
->thisconnected
= 0;
8430 l
->chan
= ast_request(deststr
, AST_FORMAT_SLINEAR
, tele
,NULL
);
8432 ast_set_read_format(l
->chan
, AST_FORMAT_SLINEAR
);
8433 ast_set_write_format(l
->chan
, AST_FORMAT_SLINEAR
);
8434 l
->chan
->whentohangup
= 0;
8435 l
->chan
->appl
= "Apprpt";
8436 l
->chan
->data
= "(Remote Rx)";
8437 if (option_verbose
> 2)
8438 ast_verbose(VERBOSE_PREFIX_3
"rpt (attempt_reconnect) initiating call to %s/%s on %s\n",
8439 deststr
, tele
, l
->chan
->name
);
8440 if(l
->chan
->cid
.cid_num
)
8441 free(l
->chan
->cid
.cid_num
);
8442 l
->chan
->cid
.cid_num
= strdup(myrpt
->name
);
8443 ast_call(l
->chan
,tele
,999);
8448 if (option_verbose
> 2)
8449 ast_verbose(VERBOSE_PREFIX_3
"Unable to place call to %s/%s on %s\n",
8450 deststr
,tele
,l
->chan
->name
);
8453 rpt_mutex_lock(&myrpt
->lock
);
8454 /* put back in queue */
8455 insque((struct qelem
*)l
,(struct qelem
*)myrpt
->links
.next
);
8456 rpt_mutex_unlock(&myrpt
->lock
);
8457 ast_log(LOG_NOTICE
,"Reconnect Attempt to %s in process\n",l
->name
);
8461 /* 0 return=continue, 1 return = break, -1 return = error */
8462 static void local_dtmf_helper(struct rpt
*myrpt
,char c
)
8465 pthread_attr_t attr
;
8466 char cmd
[MAXDTMF
+1] = "";
8468 if (myrpt
->p
.archivedir
)
8472 sprintf(str
,"DTMF,MAIN,%c",c
);
8473 donodelog(myrpt
,str
);
8475 if (c
== myrpt
->p
.endchar
)
8477 /* if in simple mode, kill autopatch */
8478 if (myrpt
->p
.simple
&& myrpt
->callmode
)
8480 rpt_mutex_lock(&myrpt
->lock
);
8481 myrpt
->callmode
= 0;
8482 rpt_mutex_unlock(&myrpt
->lock
);
8483 rpt_telemetry(myrpt
,TERM
,NULL
);
8486 rpt_mutex_lock(&myrpt
->lock
);
8488 if (myrpt
->cmdnode
[0])
8490 myrpt
->cmdnode
[0] = 0;
8491 myrpt
->dtmfidx
= -1;
8492 myrpt
->dtmfbuf
[0] = 0;
8493 rpt_mutex_unlock(&myrpt
->lock
);
8494 rpt_telemetry(myrpt
,COMPLETE
,NULL
);
8498 rpt_mutex_unlock(&myrpt
->lock
);
8499 if (myrpt
->p
.propagate_phonedtmf
)
8500 do_dtmf_phone(myrpt
,NULL
,c
);
8504 rpt_mutex_lock(&myrpt
->lock
);
8505 if (myrpt
->cmdnode
[0])
8507 rpt_mutex_unlock(&myrpt
->lock
);
8508 send_link_dtmf(myrpt
,c
);
8511 if (!myrpt
->p
.simple
)
8513 if (c
== myrpt
->p
.funcchar
)
8516 myrpt
->dtmfbuf
[myrpt
->dtmfidx
] = 0;
8517 rpt_mutex_unlock(&myrpt
->lock
);
8518 time(&myrpt
->dtmf_time
);
8521 else if ((c
!= myrpt
->p
.endchar
) && (myrpt
->dtmfidx
>= 0))
8523 time(&myrpt
->dtmf_time
);
8525 if (myrpt
->dtmfidx
< MAXDTMF
)
8527 myrpt
->dtmfbuf
[myrpt
->dtmfidx
++] = c
;
8528 myrpt
->dtmfbuf
[myrpt
->dtmfidx
] = 0;
8530 strncpy(cmd
, myrpt
->dtmfbuf
, sizeof(cmd
) - 1);
8532 rpt_mutex_unlock(&myrpt
->lock
);
8533 res
= collect_function_digits(myrpt
, cmd
, SOURCE_RPT
, NULL
);
8534 rpt_mutex_lock(&myrpt
->lock
);
8536 case DC_INDETERMINATE
:
8540 myrpt
->dtmfbuf
[0] = 0;
8543 case DC_COMPLETEQUIET
:
8544 myrpt
->totalexecdcommands
++;
8545 myrpt
->dailyexecdcommands
++;
8546 strncpy(myrpt
->lastdtmfcommand
, cmd
, MAXDTMF
-1);
8547 myrpt
->lastdtmfcommand
[MAXDTMF
-1] = '\0';
8548 myrpt
->dtmfbuf
[0] = 0;
8549 myrpt
->dtmfidx
= -1;
8550 myrpt
->dtmf_time
= 0;
8555 myrpt
->dtmfbuf
[0] = 0;
8556 myrpt
->dtmfidx
= -1;
8557 myrpt
->dtmf_time
= 0;
8560 if(res
!= DC_INDETERMINATE
) {
8561 rpt_mutex_unlock(&myrpt
->lock
);
8567 else /* if simple */
8569 if ((!myrpt
->callmode
) && (c
== myrpt
->p
.funcchar
))
8571 myrpt
->callmode
= 1;
8572 myrpt
->patchnoct
= 0;
8573 myrpt
->patchquiet
= 0;
8574 myrpt
->patchfarenddisconnect
= 0;
8575 myrpt
->patchdialtime
= 0;
8576 strncpy(myrpt
->patchcontext
, myrpt
->p
.ourcontext
, MAXPATCHCONTEXT
);
8578 myrpt
->exten
[myrpt
->cidx
] = 0;
8579 rpt_mutex_unlock(&myrpt
->lock
);
8580 pthread_attr_init(&attr
);
8581 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
8582 ast_pthread_create(&myrpt
->rpt_call_thread
,&attr
,rpt_call
,(void *)myrpt
);
8586 if (myrpt
->callmode
== 1)
8588 myrpt
->exten
[myrpt
->cidx
++] = c
;
8589 myrpt
->exten
[myrpt
->cidx
] = 0;
8590 /* if this exists */
8591 if (ast_exists_extension(myrpt
->pchannel
,myrpt
->patchcontext
,myrpt
->exten
,1,NULL
))
8593 myrpt
->callmode
= 2;
8594 rpt_mutex_unlock(&myrpt
->lock
);
8595 if(!myrpt
->patchquiet
)
8596 rpt_telemetry(myrpt
,PROC
,NULL
);
8599 /* if can continue, do so */
8600 if (!ast_canmatch_extension(myrpt
->pchannel
,myrpt
->patchcontext
,myrpt
->exten
,1,NULL
))
8602 /* call has failed, inform user */
8603 myrpt
->callmode
= 4;
8605 rpt_mutex_unlock(&myrpt
->lock
);
8608 if ((myrpt
->callmode
== 2) || (myrpt
->callmode
== 3))
8612 rpt_mutex_unlock(&myrpt
->lock
);
8613 if ((myrpt
->dtmfidx
< 0) && myrpt
->p
.propagate_phonedtmf
)
8614 do_dtmf_phone(myrpt
,NULL
,c
);
8619 /* place an ID event in the telemetry queue */
8621 static void queue_id(struct rpt
*myrpt
)
8623 if(myrpt
->p
.idtime
){ /* ID time must be non-zero */
8624 myrpt
->mustid
= myrpt
->tailid
= 0;
8625 myrpt
->idtimer
= myrpt
->p
.idtime
; /* Reset our ID timer */
8626 rpt_mutex_unlock(&myrpt
->lock
);
8627 rpt_telemetry(myrpt
,ID
,NULL
);
8628 rpt_mutex_lock(&myrpt
->lock
);
8633 /* must be called locked */
8635 static void do_scheduler(struct rpt
*myrpt
)
8639 struct ast_variable
*skedlist
;
8640 char *strs
[5],*vp
,*val
,value
[100];
8642 memcpy(&myrpt
->lasttv
, &myrpt
->curtv
, sizeof(struct timeval
));
8644 if( (res
= gettimeofday(&myrpt
->curtv
, NULL
)) < 0)
8645 ast_log(LOG_NOTICE
, "Scheduler gettime of day returned: %s\n", strerror(res
));
8647 /* Try to get close to a 1 second resolution */
8649 if(myrpt
->lasttv
.tv_sec
== myrpt
->curtv
.tv_sec
)
8652 rpt_localtime(&myrpt
->curtv
.tv_sec
, &tmnow
);
8654 /* If midnight, then reset all daily statistics */
8656 if((tmnow
.tm_hour
== 0)&&(tmnow
.tm_min
== 0)&&(tmnow
.tm_sec
== 0)){
8657 myrpt
->dailykeyups
= 0;
8658 myrpt
->dailytxtime
= 0;
8659 myrpt
->dailykerchunks
= 0;
8660 myrpt
->dailyexecdcommands
= 0;
8663 if(tmnow
.tm_sec
!= 0)
8666 /* Code below only executes once per minute */
8669 /* Don't schedule if remote */
8674 /* Don't schedule if disabled */
8676 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].schedulerdisable
){
8678 ast_log(LOG_NOTICE
, "Scheduler disabled\n");
8682 if(!myrpt
->p
.skedstanzaname
){ /* No stanza means we do nothing */
8684 ast_log(LOG_NOTICE
,"No stanza for scheduler in rpt.conf\n");
8688 /* get pointer to linked list of scheduler entries */
8689 skedlist
= ast_variable_browse(myrpt
->cfg
, myrpt
->p
.skedstanzaname
);
8692 ast_log(LOG_NOTICE
, "Time now: %02d:%02d %02d %02d %02d\n",
8693 tmnow
.tm_hour
,tmnow
.tm_min
,tmnow
.tm_mday
,tmnow
.tm_mon
+ 1, tmnow
.tm_wday
);
8696 for(; skedlist
; skedlist
= skedlist
->next
){
8698 ast_log(LOG_NOTICE
, "Scheduler entry %s = %s being considered\n",skedlist
->name
, skedlist
->value
);
8699 strncpy(value
,skedlist
->value
,99);
8701 /* point to the substrings for minute, hour, dom, month, and dow */
8702 for( i
= 0, vp
= value
; i
< 5; i
++){
8705 while((*vp
== ' ') || (*vp
== 0x09)) /* get rid of any leading white space */
8707 strs
[i
] = vp
; /* save pointer to beginning of substring */
8708 while((*vp
!= ' ') && (*vp
!= 0x09) && (*vp
!= 0)) /* skip over substring */
8711 *vp
++ = 0; /* mark end of substring */
8714 ast_log(LOG_NOTICE
, "i = %d, min = %s, hour = %s, mday=%s, mon=%s, wday=%s\n",i
,
8715 strs
[0], strs
[1], strs
[2], strs
[3], strs
[4]);
8717 if((*strs
[0] != '*')&&(atoi(strs
[0]) != tmnow
.tm_min
))
8719 if((*strs
[1] != '*')&&(atoi(strs
[1]) != tmnow
.tm_hour
))
8721 if((*strs
[2] != '*')&&(atoi(strs
[2]) != tmnow
.tm_mday
))
8723 if((*strs
[3] != '*')&&(atoi(strs
[3]) != tmnow
.tm_mon
+ 1))
8725 if(atoi(strs
[4]) == 7)
8727 if((*strs
[4] != '*')&&(atoi(strs
[4]) != tmnow
.tm_wday
))
8730 ast_log(LOG_NOTICE
, "Executing scheduler entry %s = %s\n", skedlist
->name
, skedlist
->value
);
8731 if(atoi(skedlist
->name
) == 0)
8732 return; /* Zero is reserved for the startup macro */
8733 val
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->p
.macro
, skedlist
->name
);
8735 ast_log(LOG_WARNING
,"Scheduler could not find macro %s\n",skedlist
->name
);
8736 return; /* Macro not found */
8738 if ((MAXMACRO
- strlen(myrpt
->macrobuf
)) < strlen(val
)){
8739 ast_log(LOG_WARNING
, "Scheduler could not execute macro %s: Macro buffer full\n",
8741 return; /* Macro buffer full */
8743 myrpt
->macrotimer
= MACROTIME
;
8744 strncat(myrpt
->macrobuf
,val
,MAXMACRO
- strlen(myrpt
->macrobuf
) - 1);
8747 ast_log(LOG_WARNING
,"Malformed scheduler entry in rpt.conf: %s = %s\n",
8748 skedlist
->name
, skedlist
->value
);
8754 /* single thread with one file (request) to dial */
8755 static void *rpt(void *this)
8757 struct rpt
*myrpt
= (struct rpt
*)this;
8758 char *tele
,*idtalkover
,c
;
8759 int ms
= MSWAIT
,i
,lasttx
=0,val
,remrx
=0,identqueued
,othertelemqueued
;
8760 int tailmessagequeued
,ctqueued
,dtmfed
;
8761 struct ast_channel
*who
;
8762 struct dahdi_confinfo ci
; /* conference info */
8764 struct rpt_link
*l
,*m
;
8765 struct rpt_tele
*telem
;
8766 char tmpstr
[300],lstr
[MAXLINKLIST
];
8769 if (myrpt
->p
.archivedir
) mkdir(myrpt
->p
.archivedir
,0600);
8770 sprintf(tmpstr
,"%s/%s",myrpt
->p
.archivedir
,myrpt
->name
);
8772 rpt_mutex_lock(&myrpt
->lock
);
8774 telem
= myrpt
->tele
.next
;
8775 while(telem
!= &myrpt
->tele
)
8777 ast_softhangup(telem
->chan
,AST_SOFTHANGUP_DEV
);
8778 telem
= telem
->next
;
8780 rpt_mutex_unlock(&myrpt
->lock
);
8781 /* find our index, and load the vars initially */
8782 for(i
= 0; i
< nrpts
; i
++)
8784 if (&rpt_vars
[i
] == myrpt
)
8790 rpt_mutex_lock(&myrpt
->lock
);
8791 strncpy(tmpstr
,myrpt
->rxchanname
,sizeof(tmpstr
) - 1);
8792 tele
= strchr(tmpstr
,'/');
8795 fprintf(stderr
,"rpt:Rxchannel Dial number (%s) must be in format tech/number\n",myrpt
->rxchanname
);
8796 rpt_mutex_unlock(&myrpt
->lock
);
8797 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8801 myrpt
->rxchannel
= ast_request(tmpstr
,AST_FORMAT_SLINEAR
,tele
,NULL
);
8802 myrpt
->zaprxchannel
= NULL
;
8803 if (!strcasecmp(tmpstr
,"Zap"))
8804 myrpt
->zaprxchannel
= myrpt
->rxchannel
;
8805 if (myrpt
->rxchannel
)
8807 if (myrpt
->rxchannel
->_state
== AST_STATE_BUSY
)
8809 fprintf(stderr
,"rpt:Sorry unable to obtain Rx channel\n");
8810 rpt_mutex_unlock(&myrpt
->lock
);
8811 ast_hangup(myrpt
->rxchannel
);
8812 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8815 ast_set_read_format(myrpt
->rxchannel
,AST_FORMAT_SLINEAR
);
8816 ast_set_write_format(myrpt
->rxchannel
,AST_FORMAT_SLINEAR
);
8817 #ifdef AST_CDR_FLAG_POST_DISABLED
8818 ast_set_flag(myrpt
->rxchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
8820 myrpt
->rxchannel
->whentohangup
= 0;
8821 myrpt
->rxchannel
->appl
= "Apprpt";
8822 myrpt
->rxchannel
->data
= "(Repeater Rx)";
8823 if (option_verbose
> 2)
8824 ast_verbose(VERBOSE_PREFIX_3
"rpt (Rx) initiating call to %s/%s on %s\n",
8825 tmpstr
,tele
,myrpt
->rxchannel
->name
);
8826 ast_call(myrpt
->rxchannel
,tele
,999);
8827 if (myrpt
->rxchannel
->_state
!= AST_STATE_UP
)
8829 rpt_mutex_unlock(&myrpt
->lock
);
8830 ast_hangup(myrpt
->rxchannel
);
8831 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8837 fprintf(stderr
,"rpt:Sorry unable to obtain Rx channel\n");
8838 rpt_mutex_unlock(&myrpt
->lock
);
8839 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8842 myrpt
->zaptxchannel
= NULL
;
8843 if (myrpt
->txchanname
)
8845 strncpy(tmpstr
,myrpt
->txchanname
,sizeof(tmpstr
) - 1);
8846 tele
= strchr(tmpstr
,'/');
8849 fprintf(stderr
,"rpt:Txchannel Dial number (%s) must be in format tech/number\n",myrpt
->txchanname
);
8850 rpt_mutex_unlock(&myrpt
->lock
);
8851 ast_hangup(myrpt
->rxchannel
);
8852 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8856 myrpt
->txchannel
= ast_request(tmpstr
,AST_FORMAT_SLINEAR
,tele
,NULL
);
8857 if (!strcasecmp(tmpstr
,"Zap"))
8858 myrpt
->zaptxchannel
= myrpt
->txchannel
;
8859 if (myrpt
->txchannel
)
8861 if (myrpt
->txchannel
->_state
== AST_STATE_BUSY
)
8863 fprintf(stderr
,"rpt:Sorry unable to obtain Tx channel\n");
8864 rpt_mutex_unlock(&myrpt
->lock
);
8865 ast_hangup(myrpt
->txchannel
);
8866 ast_hangup(myrpt
->rxchannel
);
8867 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8870 ast_set_read_format(myrpt
->txchannel
,AST_FORMAT_SLINEAR
);
8871 ast_set_write_format(myrpt
->txchannel
,AST_FORMAT_SLINEAR
);
8872 #ifdef AST_CDR_FLAG_POST_DISABLED
8873 ast_set_flag(myrpt
->txchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
8875 myrpt
->txchannel
->whentohangup
= 0;
8876 myrpt
->txchannel
->appl
= "Apprpt";
8877 myrpt
->txchannel
->data
= "(Repeater Tx)";
8878 if (option_verbose
> 2)
8879 ast_verbose(VERBOSE_PREFIX_3
"rpt (Tx) initiating call to %s/%s on %s\n",
8880 tmpstr
,tele
,myrpt
->txchannel
->name
);
8881 ast_call(myrpt
->txchannel
,tele
,999);
8882 if (myrpt
->rxchannel
->_state
!= AST_STATE_UP
)
8884 rpt_mutex_unlock(&myrpt
->lock
);
8885 ast_hangup(myrpt
->rxchannel
);
8886 ast_hangup(myrpt
->txchannel
);
8887 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8893 fprintf(stderr
,"rpt:Sorry unable to obtain Tx channel\n");
8894 rpt_mutex_unlock(&myrpt
->lock
);
8895 ast_hangup(myrpt
->rxchannel
);
8896 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8902 myrpt
->txchannel
= myrpt
->rxchannel
;
8904 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_KEY
);
8905 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_UNKEY
);
8906 /* allocate a pseudo-channel thru asterisk */
8907 myrpt
->pchannel
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
8908 if (!myrpt
->pchannel
)
8910 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
8911 rpt_mutex_unlock(&myrpt
->lock
);
8912 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
8913 ast_hangup(myrpt
->txchannel
);
8914 ast_hangup(myrpt
->rxchannel
);
8915 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8918 #ifdef AST_CDR_FLAG_POST_DISABLED
8919 ast_set_flag(myrpt
->pchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
8921 if (!myrpt
->zaprxchannel
) myrpt
->zaprxchannel
= myrpt
->pchannel
;
8922 if (!myrpt
->zaptxchannel
)
8924 /* allocate a pseudo-channel thru asterisk */
8925 myrpt
->zaptxchannel
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
8926 if (!myrpt
->zaptxchannel
)
8928 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
8929 rpt_mutex_unlock(&myrpt
->lock
);
8930 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
8931 ast_hangup(myrpt
->txchannel
);
8932 ast_hangup(myrpt
->rxchannel
);
8933 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8936 ast_set_read_format(myrpt
->zaptxchannel
,AST_FORMAT_SLINEAR
);
8937 ast_set_write_format(myrpt
->zaptxchannel
,AST_FORMAT_SLINEAR
);
8938 #ifdef AST_CDR_FLAG_POST_DISABLED
8939 ast_set_flag(myrpt
->zaptxchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
8942 /* allocate a pseudo-channel thru asterisk */
8943 myrpt
->monchannel
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
8944 if (!myrpt
->monchannel
)
8946 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
8947 rpt_mutex_unlock(&myrpt
->lock
);
8948 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
8949 ast_hangup(myrpt
->txchannel
);
8950 ast_hangup(myrpt
->rxchannel
);
8951 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8954 ast_set_read_format(myrpt
->monchannel
,AST_FORMAT_SLINEAR
);
8955 ast_set_write_format(myrpt
->monchannel
,AST_FORMAT_SLINEAR
);
8956 #ifdef AST_CDR_FLAG_POST_DISABLED
8957 ast_set_flag(myrpt
->monchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
8959 /* make a conference for the tx */
8961 ci
.confno
= -1; /* make a new conf */
8962 ci
.confmode
= DAHDI_CONF_CONF
| DAHDI_CONF_LISTENER
;
8963 /* first put the channel on the conference in proper mode */
8964 if (ioctl(myrpt
->zaptxchannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
8966 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
8967 rpt_mutex_unlock(&myrpt
->lock
);
8968 ast_hangup(myrpt
->pchannel
);
8969 ast_hangup(myrpt
->monchannel
);
8970 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
8971 ast_hangup(myrpt
->txchannel
);
8972 ast_hangup(myrpt
->rxchannel
);
8973 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8976 /* save tx conference number */
8977 myrpt
->txconf
= ci
.confno
;
8978 /* make a conference for the pseudo */
8980 ci
.confno
= -1; /* make a new conf */
8981 ci
.confmode
= ((myrpt
->p
.duplex
== 2) || (myrpt
->p
.duplex
== 4)) ? DAHDI_CONF_CONFANNMON
:
8982 (DAHDI_CONF_CONF
| DAHDI_CONF_LISTENER
| DAHDI_CONF_TALKER
);
8983 /* first put the channel on the conference in announce mode */
8984 if (ioctl(myrpt
->pchannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
8986 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
8987 rpt_mutex_unlock(&myrpt
->lock
);
8988 ast_hangup(myrpt
->pchannel
);
8989 ast_hangup(myrpt
->monchannel
);
8990 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
8991 ast_hangup(myrpt
->txchannel
);
8992 ast_hangup(myrpt
->rxchannel
);
8993 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
8996 /* save pseudo channel conference number */
8997 myrpt
->conf
= ci
.confno
;
8998 /* make a conference for the pseudo */
9000 if ((strstr(myrpt
->txchannel
->name
,"pseudo") == NULL
) &&
9001 (myrpt
->zaptxchannel
== myrpt
->txchannel
))
9003 /* get tx channel's port number */
9004 if (ioctl(myrpt
->txchannel
->fds
[0],DAHDI_CHANNO
,&ci
.confno
) == -1)
9006 ast_log(LOG_WARNING
, "Unable to set tx channel's chan number\n");
9007 rpt_mutex_unlock(&myrpt
->lock
);
9008 ast_hangup(myrpt
->pchannel
);
9009 ast_hangup(myrpt
->monchannel
);
9010 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
9011 ast_hangup(myrpt
->txchannel
);
9012 ast_hangup(myrpt
->rxchannel
);
9013 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
9016 ci
.confmode
= DAHDI_CONF_MONITORTX
;
9020 ci
.confno
= myrpt
->txconf
;
9021 ci
.confmode
= DAHDI_CONF_CONFANNMON
;
9023 /* first put the channel on the conference in announce mode */
9024 if (ioctl(myrpt
->monchannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
9026 ast_log(LOG_WARNING
, "Unable to set conference mode for monitor\n");
9027 rpt_mutex_unlock(&myrpt
->lock
);
9028 ast_hangup(myrpt
->pchannel
);
9029 ast_hangup(myrpt
->monchannel
);
9030 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
9031 ast_hangup(myrpt
->txchannel
);
9032 ast_hangup(myrpt
->rxchannel
);
9033 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
9036 /* allocate a pseudo-channel thru asterisk */
9037 myrpt
->txpchannel
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
9038 if (!myrpt
->txpchannel
)
9040 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
9041 rpt_mutex_unlock(&myrpt
->lock
);
9042 ast_hangup(myrpt
->pchannel
);
9043 ast_hangup(myrpt
->monchannel
);
9044 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
9045 ast_hangup(myrpt
->txchannel
);
9046 ast_hangup(myrpt
->rxchannel
);
9047 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
9050 #ifdef AST_CDR_FLAG_POST_DISABLED
9051 ast_set_flag(myrpt
->txpchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
9053 /* make a conference for the tx */
9055 ci
.confno
= myrpt
->txconf
;
9056 ci
.confmode
= DAHDI_CONF_CONF
| DAHDI_CONF_TALKER
;
9057 /* first put the channel on the conference in proper mode */
9058 if (ioctl(myrpt
->txpchannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
9060 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
9061 rpt_mutex_unlock(&myrpt
->lock
);
9062 ast_hangup(myrpt
->txpchannel
);
9063 ast_hangup(myrpt
->monchannel
);
9064 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
9065 ast_hangup(myrpt
->txchannel
);
9066 ast_hangup(myrpt
->rxchannel
);
9067 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
9070 /* Now, the idea here is to copy from the physical rx channel buffer
9071 into the pseudo tx buffer, and from the pseudo rx buffer into the
9072 tx channel buffer */
9073 myrpt
->links
.next
= &myrpt
->links
;
9074 myrpt
->links
.prev
= &myrpt
->links
;
9075 myrpt
->tailtimer
= 0;
9077 myrpt
->tmsgtimer
= myrpt
->p
.tailmessagetime
;
9078 myrpt
->idtimer
= myrpt
->p
.politeid
;
9079 myrpt
->mustid
= myrpt
->tailid
= 0;
9080 myrpt
->callmode
= 0;
9081 myrpt
->tounkeyed
= 0;
9082 myrpt
->tonotify
= 0;
9083 myrpt
->retxtimer
= 0;
9084 myrpt
->rerxtimer
= 0;
9085 myrpt
->skedtimer
= 0;
9086 myrpt
->tailevent
= 0;
9089 idtalkover
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->name
, "idtalkover");
9090 myrpt
->dtmfidx
= -1;
9091 myrpt
->dtmfbuf
[0] = 0;
9092 myrpt
->rem_dtmfidx
= -1;
9093 myrpt
->rem_dtmfbuf
[0] = 0;
9094 myrpt
->dtmf_time
= 0;
9095 myrpt
->rem_dtmf_time
= 0;
9096 myrpt
->disgorgetime
= 0;
9097 myrpt
->lastnodewhichkeyedusup
[0] = '\0';
9098 myrpt
->dailytxtime
= 0;
9099 myrpt
->totaltxtime
= 0;
9100 myrpt
->dailykeyups
= 0;
9101 myrpt
->totalkeyups
= 0;
9102 myrpt
->dailykerchunks
= 0;
9103 myrpt
->totalkerchunks
= 0;
9104 myrpt
->dailyexecdcommands
= 0;
9105 myrpt
->totalexecdcommands
= 0;
9106 myrpt
->timeouts
= 0;
9107 myrpt
->exten
[0] = '\0';
9108 myrpt
->lastdtmfcommand
[0] = '\0';
9109 if (myrpt
->p
.startupmacro
)
9111 snprintf(myrpt
->macrobuf
,MAXMACRO
- 1,"PPPP%s",myrpt
->p
.startupmacro
);
9113 rpt_mutex_unlock(&myrpt
->lock
);
9115 ast_channel_setoption(myrpt
->rxchannel
,AST_OPTION_RELAXDTMF
,&val
,sizeof(char),0);
9117 ast_channel_setoption(myrpt
->rxchannel
,AST_OPTION_TONE_VERIFY
,&val
,sizeof(char),0);
9118 if (myrpt
->p
.archivedir
) donodelog(myrpt
,"STARTUP");
9122 struct ast_frame
*f
,*f1
,*f2
;
9123 struct ast_channel
*cs
[300],*cs1
[300];
9124 int totx
=0,elap
=0,n
,x
,toexit
=0;
9127 if((myrpt
->disgorgetime
) && (time(NULL
) >= myrpt
->disgorgetime
)){
9128 struct rpt_link
*zl
;
9129 struct rpt_tele
*zt
;
9131 myrpt
->disgorgetime
= 0;
9132 ast_log(LOG_NOTICE
,"********** Variable Dump Start (app_rpt) **********\n");
9133 ast_log(LOG_NOTICE
,"totx = %d\n",totx
);
9134 ast_log(LOG_NOTICE
,"remrx = %d\n",remrx
);
9135 ast_log(LOG_NOTICE
,"lasttx = %d\n",lasttx
);
9136 ast_log(LOG_NOTICE
,"elap = %d\n",elap
);
9137 ast_log(LOG_NOTICE
,"toexit = %d\n",toexit
);
9139 ast_log(LOG_NOTICE
,"myrpt->keyed = %d\n",myrpt
->keyed
);
9140 ast_log(LOG_NOTICE
,"myrpt->localtx = %d\n",myrpt
->localtx
);
9141 ast_log(LOG_NOTICE
,"myrpt->callmode = %d\n",myrpt
->callmode
);
9142 ast_log(LOG_NOTICE
,"myrpt->mustid = %d\n",myrpt
->mustid
);
9143 ast_log(LOG_NOTICE
,"myrpt->tounkeyed = %d\n",myrpt
->tounkeyed
);
9144 ast_log(LOG_NOTICE
,"myrpt->tonotify = %d\n",myrpt
->tonotify
);
9145 ast_log(LOG_NOTICE
,"myrpt->retxtimer = %ld\n",myrpt
->retxtimer
);
9146 ast_log(LOG_NOTICE
,"myrpt->totimer = %d\n",myrpt
->totimer
);
9147 ast_log(LOG_NOTICE
,"myrpt->tailtimer = %d\n",myrpt
->tailtimer
);
9148 ast_log(LOG_NOTICE
,"myrpt->tailevent = %d\n",myrpt
->tailevent
);
9150 zl
= myrpt
->links
.next
;
9151 while(zl
!= &myrpt
->links
){
9152 ast_log(LOG_NOTICE
,"*** Link Name: %s ***\n",zl
->name
);
9153 ast_log(LOG_NOTICE
," link->lasttx %d\n",zl
->lasttx
);
9154 ast_log(LOG_NOTICE
," link->lastrx %d\n",zl
->lastrx
);
9155 ast_log(LOG_NOTICE
," link->connected %d\n",zl
->connected
);
9156 ast_log(LOG_NOTICE
," link->hasconnected %d\n",zl
->hasconnected
);
9157 ast_log(LOG_NOTICE
," link->outbound %d\n",zl
->outbound
);
9158 ast_log(LOG_NOTICE
," link->disced %d\n",zl
->disced
);
9159 ast_log(LOG_NOTICE
," link->killme %d\n",zl
->killme
);
9160 ast_log(LOG_NOTICE
," link->disctime %ld\n",zl
->disctime
);
9161 ast_log(LOG_NOTICE
," link->retrytimer %ld\n",zl
->retrytimer
);
9162 ast_log(LOG_NOTICE
," link->retries = %d\n",zl
->retries
);
9163 ast_log(LOG_NOTICE
," link->reconnects = %d\n",zl
->reconnects
);
9167 zt
= myrpt
->tele
.next
;
9168 if(zt
!= &myrpt
->tele
)
9169 ast_log(LOG_NOTICE
,"*** Telemetry Queue ***\n");
9170 while(zt
!= &myrpt
->tele
){
9171 ast_log(LOG_NOTICE
," Telemetry mode: %d\n",zt
->mode
);
9174 ast_log(LOG_NOTICE
,"******* Variable Dump End (app_rpt) *******\n");
9181 struct rpt_tele
*telem
;
9183 rpt_mutex_lock(&myrpt
->lock
);
9184 telem
= myrpt
->tele
.next
;
9185 while(telem
!= &myrpt
->tele
)
9187 ast_softhangup(telem
->chan
,AST_SOFTHANGUP_DEV
);
9188 telem
= telem
->next
;
9191 rpt_mutex_unlock(&myrpt
->lock
);
9193 /* find our index, and load the vars */
9194 for(i
= 0; i
< nrpts
; i
++)
9196 if (&rpt_vars
[i
] == myrpt
)
9204 rpt_mutex_lock(&myrpt
->lock
);
9205 if (ast_check_hangup(myrpt
->rxchannel
)) break;
9206 if (ast_check_hangup(myrpt
->txchannel
)) break;
9207 if (ast_check_hangup(myrpt
->pchannel
)) break;
9208 if (ast_check_hangup(myrpt
->monchannel
)) break;
9209 if (ast_check_hangup(myrpt
->txpchannel
)) break;
9210 if (myrpt
->zaptxchannel
&& ast_check_hangup(myrpt
->zaptxchannel
)) break;
9212 /* Set local tx with keyed */
9213 myrpt
->localtx
= myrpt
->keyed
;
9214 /* If someone's connected, and they're transmitting from their end to us, set remrx true */
9215 l
= myrpt
->links
.next
;
9217 while(l
!= &myrpt
->links
)
9221 if(l
->name
[0] != '0') /* Ignore '0' nodes */
9222 strcpy(myrpt
->lastnodewhichkeyedusup
, l
->name
); /* Note the node which is doing the key up */
9226 /* Create a "must_id" flag for the cleanup ID */
9227 if(myrpt
->p
.idtime
) /* ID time must be non-zero */
9228 myrpt
->mustid
|= (myrpt
->idtimer
) && (myrpt
->keyed
|| remrx
) ;
9229 /* Build a fresh totx from myrpt->keyed and autopatch activated */
9230 totx
= myrpt
->callmode
;
9231 /* If full duplex, add local tx to totx */
9232 if (myrpt
->p
.duplex
> 1)
9234 totx
= totx
|| myrpt
->localtx
;
9236 /* Traverse the telemetry list to see what's queued */
9238 othertelemqueued
= 0;
9239 tailmessagequeued
= 0;
9241 telem
= myrpt
->tele
.next
;
9242 while(telem
!= &myrpt
->tele
)
9244 if((telem
->mode
== ID
) || (telem
->mode
== IDTALKOVER
)){
9245 identqueued
= 1; /* Identification telemetry */
9247 else if(telem
->mode
== TAILMSG
)
9249 tailmessagequeued
= 1; /* Tail message telemetry */
9253 if ((telem
->mode
!= UNKEY
) && (telem
->mode
!= LINKUNKEY
))
9254 othertelemqueued
= 1; /* Other telemetry */
9256 ctqueued
= 1; /* Courtesy tone telemetry */
9258 telem
= telem
->next
;
9261 /* Add in any "other" telemetry, unless specified otherwise */
9262 if (!myrpt
->p
.notelemtx
) totx
= totx
|| othertelemqueued
;
9263 /* Update external (to links) transmitter PTT state with everything but ID, CT, and tailmessage telemetry */
9264 myrpt
->exttx
= totx
;
9265 totx
= totx
|| myrpt
->dtmf_local_timer
;
9266 /* If half or 3/4 duplex, add localtx to external link tx */
9267 if (myrpt
->p
.duplex
< 2) myrpt
->exttx
= myrpt
->exttx
|| myrpt
->localtx
;
9268 /* Add in ID telemetry to local transmitter */
9269 totx
= totx
|| remrx
;
9270 /* If 3/4 or full duplex, add in ident and CT telemetry */
9271 if (myrpt
->p
.duplex
> 0)
9272 totx
= totx
|| identqueued
|| ctqueued
;
9273 /* If full duplex, add local dtmf stuff active */
9274 if (myrpt
->p
.duplex
> 1)
9276 totx
= totx
|| (myrpt
->dtmfidx
> -1) ||
9279 /* Reset time out timer variables if there is no activity */
9282 myrpt
->totimer
= myrpt
->p
.totime
;
9283 myrpt
->tounkeyed
= 0;
9284 myrpt
->tonotify
= 0;
9287 myrpt
->tailtimer
= myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].alternatetail
?
9288 myrpt
->p
.althangtime
: /* Initialize tail timer */
9291 /* Disable the local transmitter if we are timed out */
9292 totx
= totx
&& myrpt
->totimer
;
9293 /* if timed-out and not said already, say it */
9294 if ((!myrpt
->totimer
) && (!myrpt
->tonotify
))
9296 myrpt
->tonotify
= 1;
9298 rpt_mutex_unlock(&myrpt
->lock
);
9299 rpt_telemetry(myrpt
,TIMEOUT
,NULL
);
9300 rpt_mutex_lock(&myrpt
->lock
);
9303 /* If unkey and re-key, reset time out timer */
9304 if ((!totx
) && (!myrpt
->totimer
) && (!myrpt
->tounkeyed
) && (!myrpt
->keyed
))
9306 myrpt
->tounkeyed
= 1;
9308 if ((!totx
) && (!myrpt
->totimer
) && myrpt
->tounkeyed
&& myrpt
->keyed
)
9310 myrpt
->totimer
= myrpt
->p
.totime
;
9311 myrpt
->tounkeyed
= 0;
9312 myrpt
->tonotify
= 0;
9313 rpt_mutex_unlock(&myrpt
->lock
);
9316 /* if timed-out and in circuit busy after call */
9317 if ((!totx
) && (!myrpt
->totimer
) && (myrpt
->callmode
== 4))
9319 myrpt
->callmode
= 0;
9321 /* get rid of tail if timed out */
9322 if (!myrpt
->totimer
) myrpt
->tailtimer
= 0;
9323 /* if not timed-out, add in tail */
9324 if (myrpt
->totimer
) totx
= totx
|| myrpt
->tailtimer
;
9325 /* If user or links key up or are keyed up over standard ID, switch to talkover ID, if one is defined */
9326 /* If tail message, kill the message if someone keys up over it */
9327 if ((myrpt
->keyed
|| remrx
) && ((identqueued
&& idtalkover
) || (tailmessagequeued
))) {
9328 int hasid
= 0,hastalkover
= 0;
9330 telem
= myrpt
->tele
.next
;
9331 while(telem
!= &myrpt
->tele
){
9332 if(telem
->mode
== ID
){
9333 if (telem
->chan
) ast_softhangup(telem
->chan
, AST_SOFTHANGUP_DEV
); /* Whoosh! */
9336 if(telem
->mode
== TAILMSG
){
9337 if (telem
->chan
) ast_softhangup(telem
->chan
, AST_SOFTHANGUP_DEV
); /* Whoosh! */
9339 if (telem
->mode
== IDTALKOVER
) hastalkover
= 1;
9340 telem
= telem
->next
;
9342 rpt_mutex_unlock(&myrpt
->lock
);
9343 if (hasid
&& (!hastalkover
)) rpt_telemetry(myrpt
, IDTALKOVER
, NULL
); /* Start Talkover ID */
9344 rpt_mutex_lock(&myrpt
->lock
);
9346 /* Try to be polite */
9347 /* If the repeater has been inactive for longer than the ID time, do an initial ID in the tail*/
9348 /* If within 30 seconds of the time to ID, try do it in the tail */
9349 /* else if at ID time limit, do it right over the top of them */
9350 /* Lastly, if the repeater has been keyed, and the ID timer is expired, do a clean up ID */
9351 if(myrpt
->mustid
&& (!myrpt
->idtimer
))
9354 if ((myrpt
->p
.idtime
&& totx
&& (!myrpt
->exttx
) &&
9355 (myrpt
->idtimer
<= myrpt
->p
.politeid
) && myrpt
->tailtimer
)) /* ID time must be non-zero */
9360 /* If tail timer expires, then check for tail messages */
9362 if(myrpt
->tailevent
){
9363 myrpt
->tailevent
= 0;
9368 else if ((myrpt
->p
.tailmessages
[0]) &&
9369 (myrpt
->p
.tailmessagetime
) && (myrpt
->tmsgtimer
== 0)){
9371 myrpt
->tmsgtimer
= myrpt
->p
.tailmessagetime
;
9372 rpt_mutex_unlock(&myrpt
->lock
);
9373 rpt_telemetry(myrpt
, TAILMSG
, NULL
);
9374 rpt_mutex_lock(&myrpt
->lock
);
9378 /* Main TX control */
9380 /* let telemetry transmit anyway (regardless of timeout) */
9381 if (myrpt
->p
.duplex
> 0) totx
= totx
|| (myrpt
->tele
.next
!= &myrpt
->tele
);
9382 if (totx
&& (!lasttx
))
9384 char mydate
[100],myfname
[100];
9387 if (myrpt
->monstream
) ast_closestream(myrpt
->monstream
);
9388 if (myrpt
->p
.archivedir
)
9393 strftime(mydate
,sizeof(mydate
) - 1,"%Y%m%d%H%M%S",
9395 sprintf(myfname
,"%s/%s/%s",myrpt
->p
.archivedir
,
9396 myrpt
->name
,mydate
);
9397 myrpt
->monstream
= ast_writefile(myfname
,"wav49",
9398 "app_rpt Air Archive",O_CREAT
| O_APPEND
,0,0600);
9399 if (myrpt
->p
.monminblocks
)
9401 blocksleft
= diskavail(myrpt
);
9402 if (blocksleft
>= myrpt
->p
.monminblocks
)
9403 donodelog(myrpt
,"TXKEY,MAIN");
9404 } else donodelog(myrpt
,"TXKEY,MAIN");
9407 myrpt
->dailykeyups
++;
9408 myrpt
->totalkeyups
++;
9409 rpt_mutex_unlock(&myrpt
->lock
);
9410 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_KEY
);
9411 rpt_mutex_lock(&myrpt
->lock
);
9413 totx
= totx
&& !myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
;
9414 if ((!totx
) && lasttx
)
9416 if (myrpt
->monstream
) ast_closestream(myrpt
->monstream
);
9417 myrpt
->monstream
= NULL
;
9420 rpt_mutex_unlock(&myrpt
->lock
);
9421 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_UNKEY
);
9422 rpt_mutex_lock(&myrpt
->lock
);
9423 donodelog(myrpt
,"TXUNKEY,MAIN");
9426 /* if DTMF timeout */
9427 if ((!myrpt
->cmdnode
[0]) && (myrpt
->dtmfidx
>= 0) && ((myrpt
->dtmf_time
+ DTMF_TIMEOUT
) < t
))
9429 myrpt
->dtmfidx
= -1;
9430 myrpt
->dtmfbuf
[0] = 0;
9432 /* if remote DTMF timeout */
9433 if ((myrpt
->rem_dtmfidx
>= 0) && ((myrpt
->rem_dtmf_time
+ DTMF_TIMEOUT
) < t
))
9435 myrpt
->rem_dtmfidx
= -1;
9436 myrpt
->rem_dtmfbuf
[0] = 0;
9441 l
= myrpt
->links
.next
;
9442 while(l
!= &myrpt
->links
)
9446 /* remove from queue */
9447 remque((struct qelem
*) l
);
9448 if (!strcmp(myrpt
->cmdnode
,l
->name
))
9449 myrpt
->cmdnode
[0] = 0;
9450 rpt_mutex_unlock(&myrpt
->lock
);
9451 /* hang-up on call to device */
9452 if (l
->chan
) ast_hangup(l
->chan
);
9453 ast_hangup(l
->pchan
);
9455 rpt_mutex_lock(&myrpt
->lock
);
9456 /* re-start link traversal */
9457 l
= myrpt
->links
.next
;
9463 cs
[n
++] = myrpt
->rxchannel
;
9464 cs
[n
++] = myrpt
->pchannel
;
9465 cs
[n
++] = myrpt
->monchannel
;
9466 cs
[n
++] = myrpt
->txpchannel
;
9467 if (myrpt
->txchannel
!= myrpt
->rxchannel
) cs
[n
++] = myrpt
->txchannel
;
9468 if (myrpt
->zaptxchannel
!= myrpt
->txchannel
)
9469 cs
[n
++] = myrpt
->zaptxchannel
;
9470 l
= myrpt
->links
.next
;
9471 while(l
!= &myrpt
->links
)
9473 if ((!l
->killme
) && (!l
->disctime
) && l
->chan
)
9480 rpt_mutex_unlock(&myrpt
->lock
);
9482 for(x
= 0; x
< n
; x
++)
9484 int s
= -(-x
- myrpt
->scram
- 1) % n
;
9488 who
= ast_waitfor_n(cs1
,n
,&ms
);
9489 if (who
== NULL
) ms
= 0;
9491 rpt_mutex_lock(&myrpt
->lock
);
9492 l
= myrpt
->links
.next
;
9493 while(l
!= &myrpt
->links
)
9495 if (l
->linklisttimer
)
9497 l
->linklisttimer
-= elap
;
9498 if (l
->linklisttimer
< 0) l
->linklisttimer
= 0;
9500 if ((!l
->linklisttimer
) && (l
->name
[0] != '0') && (!l
->isremote
))
9502 struct ast_frame lf
;
9504 memset(&lf
,0,sizeof(lf
));
9505 lf
.frametype
= AST_FRAME_TEXT
;
9510 l
->linklisttimer
= LINKLISTTIME
;
9512 __mklinklist(myrpt
,l
,lstr
+ 2);
9515 lf
.datalen
= strlen(lstr
) + 1;
9517 ast_write(l
->chan
,&lf
);
9518 if (debug
> 6) ast_log(LOG_NOTICE
,
9519 "@@@@ node %s sent node string %s to node %s\n",
9520 myrpt
->name
,lstr
,l
->name
);
9524 if ((l
->retxtimer
+= elap
) >= REDUNDANT_TX_TIME
)
9527 if (l
->chan
&& l
->phonemode
== 0)
9530 ast_indicate(l
->chan
,AST_CONTROL_RADIO_KEY
);
9532 ast_indicate(l
->chan
,AST_CONTROL_RADIO_UNKEY
);
9535 if ((l
->rerxtimer
+= elap
) >= (REDUNDANT_TX_TIME
* 5))
9537 if (debug
== 7) printf("@@@@ rx un-key\n");
9541 rpt_telemetry(myrpt
,LINKUNKEY
,l
);
9542 if (myrpt
->p
.archivedir
)
9547 sprintf(str
,"RXUNKEY(T),%s",l
->name
);
9548 donodelog(myrpt
,str
);
9552 if (l
->disctime
) /* Disconnect timer active on a channel ? */
9554 l
->disctime
-= elap
;
9555 if (l
->disctime
<= 0) /* Disconnect timer expired on inbound channel ? */
9556 l
->disctime
= 0; /* Yep */
9561 l
->retrytimer
-= elap
;
9562 if (l
->retrytimer
< 0) l
->retrytimer
= 0;
9565 /* Tally connect time */
9566 l
->connecttime
+= elap
;
9568 /* ignore non-timing channels */
9569 if (l
->elaptime
< 0)
9574 l
->elaptime
+= elap
;
9575 /* if connection has taken too long */
9576 if ((l
->elaptime
> MAXCONNECTTIME
) &&
9577 ((!l
->chan
) || (l
->chan
->_state
!= AST_STATE_UP
)))
9580 rpt_mutex_unlock(&myrpt
->lock
);
9581 if (l
->chan
) ast_softhangup(l
->chan
,AST_SOFTHANGUP_DEV
);
9582 rpt_mutex_lock(&myrpt
->lock
);
9585 if ((!l
->chan
) && (!l
->retrytimer
) && l
->outbound
&&
9586 (l
->retries
++ < l
->max_retries
) && (l
->hasconnected
))
9588 if (l
->chan
) ast_hangup(l
->chan
);
9590 rpt_mutex_unlock(&myrpt
->lock
);
9591 if ((l
->name
[0] != '0') && (!l
->isremote
))
9593 if (attempt_reconnect(myrpt
,l
) == -1)
9595 l
->retrytimer
= RETRY_TIMER_MS
;
9600 l
->retrytimer
= l
->max_retries
+ 1;
9603 rpt_mutex_lock(&myrpt
->lock
);
9606 if ((!l
->chan
) && (!l
->retrytimer
) && l
->outbound
&&
9607 (l
->retries
>= l
->max_retries
))
9609 /* remove from queue */
9610 remque((struct qelem
*) l
);
9611 if (!strcmp(myrpt
->cmdnode
,l
->name
))
9612 myrpt
->cmdnode
[0] = 0;
9613 rpt_mutex_unlock(&myrpt
->lock
);
9614 if (l
->name
[0] != '0')
9616 if (!l
->hasconnected
)
9617 rpt_telemetry(myrpt
,CONNFAIL
,l
);
9618 else rpt_telemetry(myrpt
,REMDISC
,l
);
9620 if (myrpt
->p
.archivedir
)
9624 if (!l
->hasconnected
)
9625 sprintf(str
,"LINKFAIL,%s",l
->name
);
9627 sprintf(str
,"LINKDISC,%s",l
->name
);
9628 donodelog(myrpt
,str
);
9630 /* hang-up on call to device */
9631 ast_hangup(l
->pchan
);
9633 rpt_mutex_lock(&myrpt
->lock
);
9636 if ((!l
->chan
) && (!l
->disctime
) && (!l
->outbound
))
9638 /* remove from queue */
9639 remque((struct qelem
*) l
);
9640 if (!strcmp(myrpt
->cmdnode
,l
->name
))
9641 myrpt
->cmdnode
[0] = 0;
9642 rpt_mutex_unlock(&myrpt
->lock
);
9643 if (l
->name
[0] != '0')
9645 rpt_telemetry(myrpt
,REMDISC
,l
);
9647 if (myrpt
->p
.archivedir
)
9651 sprintf(str
,"LINKDISC,%s",l
->name
);
9652 donodelog(myrpt
,str
);
9654 /* hang-up on call to device */
9655 ast_hangup(l
->pchan
);
9657 rpt_mutex_lock(&myrpt
->lock
);
9663 myrpt
->dailytxtime
+= elap
;
9664 myrpt
->totaltxtime
+= elap
;
9666 i
= myrpt
->tailtimer
;
9667 if (myrpt
->tailtimer
) myrpt
->tailtimer
-= elap
;
9668 if (myrpt
->tailtimer
< 0) myrpt
->tailtimer
= 0;
9669 if((i
) && (myrpt
->tailtimer
== 0))
9670 myrpt
->tailevent
= 1;
9671 if ((!myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].totdisable
) && myrpt
->totimer
) myrpt
->totimer
-= elap
;
9672 if (myrpt
->totimer
< 0) myrpt
->totimer
= 0;
9673 if (myrpt
->idtimer
) myrpt
->idtimer
-= elap
;
9674 if (myrpt
->idtimer
< 0) myrpt
->idtimer
= 0;
9675 if (myrpt
->tmsgtimer
) myrpt
->tmsgtimer
-= elap
;
9676 if (myrpt
->tmsgtimer
< 0) myrpt
->tmsgtimer
= 0;
9677 /* do macro timers */
9678 if (myrpt
->macrotimer
) myrpt
->macrotimer
-= elap
;
9679 if (myrpt
->macrotimer
< 0) myrpt
->macrotimer
= 0;
9680 /* do local dtmf timer */
9681 if (myrpt
->dtmf_local_timer
)
9683 if (myrpt
->dtmf_local_timer
> 1) myrpt
->dtmf_local_timer
-= elap
;
9684 if (myrpt
->dtmf_local_timer
< 1) myrpt
->dtmf_local_timer
= 1;
9686 do_dtmf_local(myrpt
,0);
9687 /* Execute scheduler appx. every 2 tenths of a second */
9688 if (myrpt
->skedtimer
<= 0){
9689 myrpt
->skedtimer
= 200;
9690 do_scheduler(myrpt
);
9693 myrpt
->skedtimer
-=elap
;
9696 rpt_mutex_unlock(&myrpt
->lock
);
9699 c
= myrpt
->macrobuf
[0];
9701 if (c
&& (!myrpt
->macrotimer
) &&
9702 starttime
&& (t
> (starttime
+ START_DELAY
)))
9704 myrpt
->macrotimer
= MACROTIME
;
9705 memmove(myrpt
->macrobuf
,myrpt
->macrobuf
+ 1,MAXMACRO
- 1);
9706 if ((c
== 'p') || (c
== 'P'))
9707 myrpt
->macrotimer
= MACROPTIME
;
9708 rpt_mutex_unlock(&myrpt
->lock
);
9709 if (myrpt
->p
.archivedir
)
9713 sprintf(str
,"DTMF(M),MAIN,%c",c
);
9714 donodelog(myrpt
,str
);
9716 local_dtmf_helper(myrpt
,c
);
9717 } else rpt_mutex_unlock(&myrpt
->lock
);
9718 if (who
== myrpt
->rxchannel
) /* if it was a read from rx */
9722 f
= ast_read(myrpt
->rxchannel
);
9725 if (debug
) printf("@@@@ rpt:Hung Up\n");
9728 if (f
->frametype
== AST_FRAME_VOICE
)
9730 #ifdef _MDC_DECODE_H_
9731 unsigned char ubuf
[2560];
9736 if ((!myrpt
->localtx
) && (!myrpt
->p
.linktolink
)) {
9737 memset(f
->data
,0,f
->datalen
);
9740 #ifdef _MDC_DECODE_H_
9741 sp
= (short *) f
->data
;
9742 /* convert block to unsigned char */
9743 for(n
= 0; n
< f
->datalen
/ 2; n
++)
9745 ubuf
[n
] = (*sp
++ >> 8) + 128;
9747 n
= mdc_decoder_process_samples(myrpt
->mdc
,ubuf
,f
->datalen
/ 2);
9750 unsigned char op
,arg
;
9751 unsigned short unitID
;
9753 mdc_decoder_get_packet(myrpt
->mdc
,&op
,&arg
,&unitID
);
9756 ast_log(LOG_NOTICE
,"Got (single-length) packet:\n");
9757 ast_log(LOG_NOTICE
,"op: %02x, arg: %02x, UnitID: %04x\n",
9758 op
& 255,arg
& 255,unitID
);
9760 if ((op
== 1) && (arg
== 0))
9762 myrpt
->lastunit
= unitID
;
9763 mdc1200_notify(myrpt
,NULL
,myrpt
->lastunit
);
9764 mdc1200_send(myrpt
,myrpt
->lastunit
);
9767 if ((debug
> 2) && (i
== 2))
9769 unsigned char op
,arg
,ex1
,ex2
,ex3
,ex4
;
9770 unsigned short unitID
;
9772 mdc_decoder_get_double_packet(myrpt
->mdc
,&op
,&arg
,&unitID
,
9773 &ex1
,&ex2
,&ex3
,&ex4
);
9774 ast_log(LOG_NOTICE
,"Got (double-length) packet:\n");
9775 ast_log(LOG_NOTICE
,"op: %02x, arg: %02x, UnitID: %04x\n",
9776 op
& 255,arg
& 255,unitID
);
9777 ast_log(LOG_NOTICE
,"ex1: %02x, ex2: %02x, ex3: %02x, ex4: %02x\n",
9778 ex1
& 255, ex2
& 255, ex3
& 255, ex4
& 255);
9782 /* apply inbound filters, if any */
9783 rpt_filter(myrpt
,f
->data
,f
->datalen
/ 2);
9785 if (ioctl(myrpt
->zaprxchannel
->fds
[0], DAHDI_GETCONFMUTE
, &ismuted
) == -1)
9789 if (dtmfed
) ismuted
= 1;
9793 memset(f
->data
,0,f
->datalen
);
9795 memset(myrpt
->lastf1
->data
,0,myrpt
->lastf1
->datalen
);
9797 memset(myrpt
->lastf2
->data
,0,myrpt
->lastf2
->datalen
);
9799 if (f
) f2
= ast_frdup(f
);
9802 myrpt
->lastf2
= myrpt
->lastf1
;
9807 memset(myrpt
->lastf1
->data
,0,myrpt
->lastf1
->datalen
);
9809 memset(myrpt
->lastf2
->data
,0,myrpt
->lastf2
->datalen
);
9813 ast_write(myrpt
->pchannel
,f1
);
9817 #ifndef OLD_ASTERISK
9818 else if (f
->frametype
== AST_FRAME_DTMF_BEGIN
)
9821 memset(myrpt
->lastf1
->data
,0,myrpt
->lastf1
->datalen
);
9823 memset(myrpt
->lastf2
->data
,0,myrpt
->lastf2
->datalen
);
9827 else if (f
->frametype
== AST_FRAME_DTMF
)
9829 c
= (char) f
->subclass
; /* get DTMF char */
9832 memset(myrpt
->lastf1
->data
,0,myrpt
->lastf1
->datalen
);
9834 memset(myrpt
->lastf2
->data
,0,myrpt
->lastf2
->datalen
);
9836 if (!myrpt
->keyed
) continue;
9837 c
= func_xlat(myrpt
,c
,&myrpt
->p
.inxlat
);
9838 if (c
) local_dtmf_helper(myrpt
,c
);
9841 else if (f
->frametype
== AST_FRAME_CONTROL
)
9843 if (f
->subclass
== AST_CONTROL_HANGUP
)
9845 if (debug
) printf("@@@@ rpt:Hung Up\n");
9850 if (f
->subclass
== AST_CONTROL_RADIO_KEY
)
9852 if ((!lasttx
) || (myrpt
->p
.duplex
> 1) || (myrpt
->p
.linktolink
))
9854 if (debug
== 7) printf("@@@@ rx key\n");
9857 if (myrpt
->p
.archivedir
)
9859 donodelog(myrpt
,"RXKEY,MAIN");
9863 if (f
->subclass
== AST_CONTROL_RADIO_UNKEY
)
9865 if ((!lasttx
) || (myrpt
->p
.duplex
> 1) || (myrpt
->p
.linktolink
))
9867 if (debug
== 7) printf("@@@@ rx un-key\n");
9868 if(myrpt
->p
.duplex
&& myrpt
->keyed
) {
9869 rpt_telemetry(myrpt
,UNKEY
,NULL
);
9873 if (myrpt
->p
.archivedir
)
9875 donodelog(myrpt
,"RXUNKEY,MAIN");
9882 if (who
== myrpt
->pchannel
) /* if it was a read from pseudo */
9884 f
= ast_read(myrpt
->pchannel
);
9887 if (debug
) printf("@@@@ rpt:Hung Up\n");
9890 if (f
->frametype
== AST_FRAME_VOICE
)
9892 ast_write(myrpt
->txpchannel
,f
);
9894 if (f
->frametype
== AST_FRAME_CONTROL
)
9896 if (f
->subclass
== AST_CONTROL_HANGUP
)
9898 if (debug
) printf("@@@@ rpt:Hung Up\n");
9906 if (who
== myrpt
->txchannel
) /* if it was a read from tx */
9908 f
= ast_read(myrpt
->txchannel
);
9911 if (debug
) printf("@@@@ rpt:Hung Up\n");
9914 if (f
->frametype
== AST_FRAME_CONTROL
)
9916 if (f
->subclass
== AST_CONTROL_HANGUP
)
9918 if (debug
) printf("@@@@ rpt:Hung Up\n");
9926 if (who
== myrpt
->zaptxchannel
) /* if it was a read from pseudo-tx */
9928 f
= ast_read(myrpt
->zaptxchannel
);
9931 if (debug
) printf("@@@@ rpt:Hung Up\n");
9934 if (f
->frametype
== AST_FRAME_VOICE
)
9936 ast_write(myrpt
->txchannel
,f
);
9938 if (f
->frametype
== AST_FRAME_CONTROL
)
9940 if (f
->subclass
== AST_CONTROL_HANGUP
)
9942 if (debug
) printf("@@@@ rpt:Hung Up\n");
9951 rpt_mutex_lock(&myrpt
->lock
);
9952 l
= myrpt
->links
.next
;
9953 while(l
!= &myrpt
->links
)
9960 if (who
== l
->chan
) /* if it was a read from rx */
9965 /* see if any other links are receiving */
9966 m
= myrpt
->links
.next
;
9967 while(m
!= &myrpt
->links
)
9969 /* if not us, count it */
9970 if ((m
!= l
) && (m
->lastrx
)) remrx
= 1;
9973 rpt_mutex_unlock(&myrpt
->lock
);
9974 remnomute
= myrpt
->localtx
&&
9975 (!(myrpt
->cmdnode
[0] ||
9976 (myrpt
->dtmfidx
> -1)));
9977 totx
= (((l
->isremote
) ? (remnomute
) :
9978 myrpt
->exttx
) || remrx
) && l
->mode
;
9979 if (l
->phonemode
== 0 && l
->chan
&& (l
->lasttx
!= totx
))
9983 ast_indicate(l
->chan
,AST_CONTROL_RADIO_KEY
);
9987 ast_indicate(l
->chan
,AST_CONTROL_RADIO_UNKEY
);
9989 if (myrpt
->p
.archivedir
)
9994 sprintf(str
,"TXKEY,%s",l
->name
);
9996 sprintf(str
,"TXUNKEY,%s",l
->name
);
9997 donodelog(myrpt
,str
);
10001 f
= ast_read(l
->chan
);
10004 rpt_mutex_lock(&myrpt
->lock
);
10005 __kickshort(myrpt
);
10006 rpt_mutex_unlock(&myrpt
->lock
);
10007 if ((!l
->disced
) && (!l
->outbound
))
10009 if ((l
->name
[0] == '0') || l
->isremote
)
10012 l
->disctime
= DISC_TIME
;
10013 rpt_mutex_lock(&myrpt
->lock
);
10014 ast_hangup(l
->chan
);
10021 ast_hangup(l
->chan
);
10023 rpt_mutex_lock(&myrpt
->lock
);
10026 if (l
->outbound
&& (l
->retries
++ < l
->max_retries
) && (l
->hasconnected
))
10028 rpt_mutex_lock(&myrpt
->lock
);
10029 if (l
->chan
) ast_hangup(l
->chan
);
10031 l
->hasconnected
= 1;
10032 l
->retrytimer
= RETRY_TIMER_MS
;
10034 l
->connecttime
= 0;
10035 l
->thisconnected
= 0;
10038 rpt_mutex_lock(&myrpt
->lock
);
10039 /* remove from queue */
10040 remque((struct qelem
*) l
);
10041 if (!strcmp(myrpt
->cmdnode
,l
->name
))
10042 myrpt
->cmdnode
[0] = 0;
10043 __kickshort(myrpt
);
10044 rpt_mutex_unlock(&myrpt
->lock
);
10045 if (!l
->hasconnected
)
10046 rpt_telemetry(myrpt
,CONNFAIL
,l
);
10047 else if (l
->disced
!= 2) rpt_telemetry(myrpt
,REMDISC
,l
);
10048 if (myrpt
->p
.archivedir
)
10052 if (!l
->hasconnected
)
10053 sprintf(str
,"LINKFAIL,%s",l
->name
);
10055 sprintf(str
,"LINKDISC,%s",l
->name
);
10056 donodelog(myrpt
,str
);
10058 if (l
->lastf1
) ast_frfree(l
->lastf1
);
10060 if (l
->lastf2
) ast_frfree(l
->lastf2
);
10062 /* hang-up on call to device */
10063 ast_hangup(l
->chan
);
10064 ast_hangup(l
->pchan
);
10066 rpt_mutex_lock(&myrpt
->lock
);
10069 if (f
->frametype
== AST_FRAME_VOICE
)
10075 if (ioctl(l
->chan
->fds
[0], DAHDI_GETCONFMUTE
, &ismuted
) == -1)
10079 /* if not receiving, zero-out audio */
10080 ismuted
|= (!l
->lastrx
);
10081 if (l
->dtmfed
&& l
->phonemode
) ismuted
= 1;
10085 memset(f
->data
,0,f
->datalen
);
10087 memset(l
->lastf1
->data
,0,l
->lastf1
->datalen
);
10089 memset(l
->lastf2
->data
,0,l
->lastf2
->datalen
);
10091 if (f
) f2
= ast_frdup(f
);
10094 l
->lastf2
= l
->lastf1
;
10099 memset(l
->lastf1
->data
,0,l
->lastf1
->datalen
);
10101 memset(l
->lastf2
->data
,0,l
->lastf2
->datalen
);
10105 ast_write(l
->pchan
,f1
);
10112 memset(f
->data
,0,f
->datalen
);
10113 ast_write(l
->pchan
,f
);
10116 #ifndef OLD_ASTERISK
10117 else if (f
->frametype
== AST_FRAME_DTMF_BEGIN
)
10120 memset(l
->lastf1
->data
,0,l
->lastf1
->datalen
);
10122 memset(l
->lastf2
->data
,0,l
->lastf2
->datalen
);
10127 if (f
->frametype
== AST_FRAME_TEXT
)
10129 handle_link_data(myrpt
,l
,f
->data
);
10131 if (f
->frametype
== AST_FRAME_DTMF
)
10134 memset(l
->lastf1
->data
,0,l
->lastf1
->datalen
);
10136 memset(l
->lastf2
->data
,0,l
->lastf2
->datalen
);
10138 handle_link_phone_dtmf(myrpt
,l
,f
->subclass
);
10140 if (f
->frametype
== AST_FRAME_CONTROL
)
10142 if (f
->subclass
== AST_CONTROL_ANSWER
)
10144 char lconnected
= l
->connected
;
10146 __kickshort(myrpt
);
10148 l
->hasconnected
= 1;
10149 l
->thisconnected
= 1;
10151 if (!l
->isremote
) l
->retries
= 0;
10154 rpt_telemetry(myrpt
,CONNECTED
,l
);
10155 if (myrpt
->p
.archivedir
)
10160 sprintf(str
,"LINKTRX,%s",l
->name
);
10162 sprintf(str
,"LINKMONITOR,%s",l
->name
);
10163 donodelog(myrpt
,str
);
10170 if (f
->subclass
== AST_CONTROL_RADIO_KEY
)
10172 if (debug
== 7 ) printf("@@@@ rx key\n");
10175 if (myrpt
->p
.archivedir
&& (!l
->lastrx1
))
10180 sprintf(str
,"RXKEY,%s",l
->name
);
10181 donodelog(myrpt
,str
);
10185 if (f
->subclass
== AST_CONTROL_RADIO_UNKEY
)
10187 if (debug
== 7) printf("@@@@ rx un-key\n");
10190 if(myrpt
->p
.duplex
)
10191 rpt_telemetry(myrpt
,LINKUNKEY
,l
);
10192 if (myrpt
->p
.archivedir
&& (l
->lastrx1
))
10197 sprintf(str
,"RXUNKEY,%s",l
->name
);
10198 donodelog(myrpt
,str
);
10201 if (f
->subclass
== AST_CONTROL_HANGUP
)
10204 rpt_mutex_lock(&myrpt
->lock
);
10205 __kickshort(myrpt
);
10206 rpt_mutex_unlock(&myrpt
->lock
);
10207 if ((!l
->outbound
) && (!l
->disced
))
10209 if ((l
->name
[0] == '0') || l
->isremote
)
10212 l
->disctime
= DISC_TIME
;
10213 rpt_mutex_lock(&myrpt
->lock
);
10214 ast_hangup(l
->chan
);
10220 if (l
->chan
) ast_hangup(l
->chan
);
10222 rpt_mutex_lock(&myrpt
->lock
);
10225 if (l
->outbound
&& (l
->retries
++ < l
->max_retries
) && (l
->hasconnected
))
10227 rpt_mutex_lock(&myrpt
->lock
);
10228 if (l
->chan
) ast_hangup(l
->chan
);
10230 l
->hasconnected
= 1;
10232 l
->retrytimer
= RETRY_TIMER_MS
;
10233 l
->connecttime
= 0;
10234 l
->thisconnected
= 0;
10237 rpt_mutex_lock(&myrpt
->lock
);
10238 /* remove from queue */
10239 remque((struct qelem
*) l
);
10240 if (!strcmp(myrpt
->cmdnode
,l
->name
))
10241 myrpt
->cmdnode
[0] = 0;
10242 __kickshort(myrpt
);
10243 rpt_mutex_unlock(&myrpt
->lock
);
10244 if (!l
->hasconnected
)
10245 rpt_telemetry(myrpt
,CONNFAIL
,l
);
10246 else if (l
->disced
!= 2) rpt_telemetry(myrpt
,REMDISC
,l
);
10247 if (myrpt
->p
.archivedir
)
10251 if (!l
->hasconnected
)
10252 sprintf(str
,"LINKFAIL,%s",l
->name
);
10254 sprintf(str
,"LINKDISC,%s",l
->name
);
10255 donodelog(myrpt
,str
);
10257 if (l
->lastf1
) ast_frfree(l
->lastf1
);
10259 if (l
->lastf2
) ast_frfree(l
->lastf2
);
10261 /* hang-up on call to device */
10262 ast_hangup(l
->chan
);
10263 ast_hangup(l
->pchan
);
10265 rpt_mutex_lock(&myrpt
->lock
);
10270 rpt_mutex_lock(&myrpt
->lock
);
10273 if (who
== l
->pchan
)
10275 rpt_mutex_unlock(&myrpt
->lock
);
10276 f
= ast_read(l
->pchan
);
10279 if (debug
) printf("@@@@ rpt:Hung Up\n");
10281 rpt_mutex_lock(&myrpt
->lock
);
10284 if (f
->frametype
== AST_FRAME_VOICE
)
10286 if (l
->chan
) ast_write(l
->chan
,f
);
10288 if (f
->frametype
== AST_FRAME_CONTROL
)
10290 if (f
->subclass
== AST_CONTROL_HANGUP
)
10292 if (debug
) printf("@@@@ rpt:Hung Up\n");
10295 rpt_mutex_lock(&myrpt
->lock
);
10300 rpt_mutex_lock(&myrpt
->lock
);
10305 rpt_mutex_unlock(&myrpt
->lock
);
10307 if (who
== myrpt
->monchannel
)
10309 f
= ast_read(myrpt
->monchannel
);
10312 if (debug
) printf("@@@@ rpt:Hung Up\n");
10315 if (f
->frametype
== AST_FRAME_VOICE
)
10317 if (myrpt
->monstream
)
10318 ast_writestream(myrpt
->monstream
,f
);
10320 if (f
->frametype
== AST_FRAME_CONTROL
)
10322 if (f
->subclass
== AST_CONTROL_HANGUP
)
10324 if (debug
) printf("@@@@ rpt:Hung Up\n");
10332 if (who
== myrpt
->txpchannel
) /* if it was a read from remote tx */
10334 f
= ast_read(myrpt
->txpchannel
);
10337 if (debug
) printf("@@@@ rpt:Hung Up\n");
10340 if (f
->frametype
== AST_FRAME_CONTROL
)
10342 if (f
->subclass
== AST_CONTROL_HANGUP
)
10344 if (debug
) printf("@@@@ rpt:Hung Up\n");
10354 ast_hangup(myrpt
->pchannel
);
10355 ast_hangup(myrpt
->monchannel
);
10356 ast_hangup(myrpt
->txpchannel
);
10357 if (myrpt
->txchannel
!= myrpt
->rxchannel
) ast_hangup(myrpt
->txchannel
);
10358 if (myrpt
->zaptxchannel
!= myrpt
->txchannel
) ast_hangup(myrpt
->zaptxchannel
);
10359 if (myrpt
->lastf1
) ast_frfree(myrpt
->lastf1
);
10360 myrpt
->lastf1
= NULL
;
10361 if (myrpt
->lastf2
) ast_frfree(myrpt
->lastf2
);
10362 myrpt
->lastf2
= NULL
;
10363 ast_hangup(myrpt
->rxchannel
);
10364 rpt_mutex_lock(&myrpt
->lock
);
10365 l
= myrpt
->links
.next
;
10366 while(l
!= &myrpt
->links
)
10368 struct rpt_link
*ll
= l
;
10369 /* remove from queue */
10370 remque((struct qelem
*) l
);
10371 /* hang-up on call to device */
10372 if (l
->chan
) ast_hangup(l
->chan
);
10373 ast_hangup(l
->pchan
);
10377 rpt_mutex_unlock(&myrpt
->lock
);
10378 if (debug
) printf("@@@@ rpt:Hung up channel\n");
10379 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
10380 pthread_exit(NULL
);
10385 static void *rpt_master(void *ignore
)
10388 pthread_attr_t attr
;
10389 struct ast_config
*cfg
;
10392 /* init nodelog queue */
10393 nodelog
.next
= nodelog
.prev
= &nodelog
;
10394 /* go thru all the specified repeaters */
10397 /* wait until asterisk starts */
10398 while(!ast_test_flag(&ast_options
,AST_OPT_FLAG_FULLY_BOOTED
))
10400 rpt_vars
[n
].cfg
= ast_config_load("rpt.conf");
10401 cfg
= rpt_vars
[n
].cfg
;
10403 ast_log(LOG_NOTICE
, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
10404 pthread_exit(NULL
);
10406 while((this = ast_category_browse(cfg
,this)) != NULL
)
10408 for(i
= 0 ; i
< strlen(this) ; i
++){
10409 if((this[i
] < '0') || (this[i
] > '9'))
10412 if(i
!= strlen(this)) continue; /* Not a node defn */
10413 memset(&rpt_vars
[n
],0,sizeof(rpt_vars
[n
]));
10414 rpt_vars
[n
].name
= strdup(this);
10415 val
= (char *) ast_variable_retrieve(cfg
,this,"rxchannel");
10416 if (val
) rpt_vars
[n
].rxchanname
= strdup(val
);
10417 val
= (char *) ast_variable_retrieve(cfg
,this,"txchannel");
10418 if (val
) rpt_vars
[n
].txchanname
= strdup(val
);
10419 val
= (char *) ast_variable_retrieve(cfg
,this,"remote");
10420 if (val
) rpt_vars
[n
].remote
= strdup(val
);
10421 ast_mutex_init(&rpt_vars
[n
].lock
);
10422 ast_mutex_init(&rpt_vars
[n
].remlock
);
10423 rpt_vars
[n
].tele
.next
= &rpt_vars
[n
].tele
;
10424 rpt_vars
[n
].tele
.prev
= &rpt_vars
[n
].tele
;
10425 rpt_vars
[n
].rpt_thread
= AST_PTHREADT_NULL
;
10426 rpt_vars
[n
].tailmessagen
= 0;
10427 #ifdef _MDC_DECODE_H_
10428 rpt_vars
[n
].mdc
= mdc_decoder_new(8000);
10433 ast_config_destroy(cfg
);
10436 for(i
= 0; i
< n
; i
++)
10438 load_rpt_vars(i
,1);
10440 /* if is a remote, dont start one for it */
10441 if (rpt_vars
[i
].remote
)
10443 if(retreive_memory(&rpt_vars
[i
],"init")){ /* Try to retreive initial memory channel */
10444 strncpy(rpt_vars
[i
].freq
, "146.580", sizeof(rpt_vars
[i
].freq
) - 1);
10445 strncpy(rpt_vars
[i
].rxpl
, "100.0", sizeof(rpt_vars
[i
].rxpl
) - 1);
10447 strncpy(rpt_vars
[i
].txpl
, "100.0", sizeof(rpt_vars
[i
].txpl
) - 1);
10448 rpt_vars
[i
].remmode
= REM_MODE_FM
;
10449 rpt_vars
[i
].offset
= REM_SIMPLEX
;
10450 rpt_vars
[i
].powerlevel
= REM_MEDPWR
;
10454 if (!rpt_vars
[i
].p
.ident
)
10456 ast_log(LOG_WARNING
,"Did not specify ident for node %s\n",rpt_vars
[i
].name
);
10457 ast_config_destroy(cfg
);
10458 pthread_exit(NULL
);
10460 pthread_attr_init(&attr
);
10461 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
10462 ast_pthread_create(&rpt_vars
[i
].rpt_thread
,&attr
,rpt
,(void *) &rpt_vars
[i
]);
10468 /* Now monitor each thread, and restart it if necessary */
10469 for(i
= 0; i
< n
; i
++)
10472 if (rpt_vars
[i
].remote
) continue;
10473 if (rpt_vars
[i
].rpt_thread
== AST_PTHREADT_STOP
)
10476 rv
= pthread_kill(rpt_vars
[i
].rpt_thread
,0);
10479 if(time(NULL
) - rpt_vars
[i
].lastthreadrestarttime
<= 15)
10481 if(rpt_vars
[i
].threadrestarts
>= 5)
10483 ast_log(LOG_ERROR
,"Continual RPT thread restarts, killing Asterisk\n");
10484 exit(1); /* Stuck in a restart loop, kill Asterisk and start over */
10488 ast_log(LOG_NOTICE
,"RPT thread restarted on %s\n",rpt_vars
[i
].name
);
10489 rpt_vars
[i
].threadrestarts
++;
10493 rpt_vars
[i
].threadrestarts
= 0;
10495 rpt_vars
[i
].lastthreadrestarttime
= time(NULL
);
10496 pthread_attr_init(&attr
);
10497 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
10498 ast_pthread_create(&rpt_vars
[i
].rpt_thread
,&attr
,rpt
,(void *) &rpt_vars
[i
]);
10499 ast_log(LOG_WARNING
, "rpt_thread restarted on node %s\n", rpt_vars
[i
].name
);
10505 struct nodelog
*nodep
;
10506 char *space
,datestr
[100],fname
[300];
10509 ast_mutex_lock(&nodeloglock
);
10510 nodep
= nodelog
.next
;
10511 if(nodep
== &nodelog
) /* if nothing in queue */
10513 ast_mutex_unlock(&nodeloglock
);
10516 remque((struct qelem
*)nodep
);
10517 ast_mutex_unlock(&nodeloglock
);
10518 space
= strchr(nodep
->str
,' ');
10525 strftime(datestr
,sizeof(datestr
) - 1,"%Y%m%d",
10526 localtime(&nodep
->timestamp
));
10527 sprintf(fname
,"%s/%s/%s.txt",nodep
->archivedir
,
10528 nodep
->str
,datestr
);
10529 fd
= open(fname
,O_WRONLY
| O_CREAT
| O_APPEND
,0600);
10532 ast_log(LOG_ERROR
,"Cannot open node log file %s for write",space
+ 1);
10536 if (write(fd
,space
+ 1,strlen(space
+ 1)) !=
10539 ast_log(LOG_ERROR
,"Cannot write node log file %s for write",space
+ 1);
10548 ast_config_destroy(cfg
);
10549 pthread_exit(NULL
);
10552 static int rpt_exec(struct ast_channel
*chan
, void *data
)
10554 int res
=-1,i
,rem_totx
,rem_rx
,remkeyed
,n
,phone_mode
= 0;
10555 int iskenwood_pci4
,authtold
,authreq
,setting
,notremming
,reming
;
10556 int ismuted
,dtmfed
;
10557 #ifdef OLD_ASTERISK
10558 struct localuser
*u
;
10560 char tmp
[256], keyed
= 0,keyed1
= 0;
10561 char *options
,*stringp
,*tele
,c
;
10563 struct ast_frame
*f
,*f1
,*f2
;
10564 struct ast_channel
*who
;
10565 struct ast_channel
*cs
[20];
10566 struct rpt_link
*l
;
10567 struct dahdi_confinfo ci
; /* conference info */
10568 struct dahdi_params par
;
10569 int ms
,elap
,nullfd
;
10570 time_t t
,last_timeout_warning
;
10571 struct dahdi_radio_param z
;
10572 struct rpt_tele
*telem
;
10574 nullfd
= open("/dev/null",O_RDWR
);
10575 if (ast_strlen_zero(data
)) {
10576 ast_log(LOG_WARNING
, "Rpt requires an argument (system node)\n");
10580 strncpy(tmp
, (char *)data
, sizeof(tmp
)-1);
10582 /* if time has externally shifted negative, screw it */
10583 if (t
< starttime
) t
= starttime
+ START_DELAY
;
10584 if ((!starttime
) || (t
< (starttime
+ START_DELAY
)))
10586 ast_log(LOG_NOTICE
,"Node %s rejecting call: too soon!\n",tmp
);
10587 ast_safe_sleep(chan
,3000);
10591 strsep(&stringp
, "|");
10594 /* see if we can find our specified one */
10595 for(i
= 0; i
< nrpts
; i
++)
10597 /* if name matches, assign it and exit loop */
10598 if (!strcmp(tmp
,rpt_vars
[i
].name
))
10600 myrpt
= &rpt_vars
[i
];
10606 ast_log(LOG_WARNING
, "Cannot find specified system node %s\n",tmp
);
10610 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
){ /* Do not allow incoming connections if disabled */
10611 ast_log(LOG_NOTICE
, "Connect attempt to node %s with tx disabled", myrpt
->name
);
10615 /* if not phone access, must be an IAX connection */
10616 if (options
&& ((*options
== 'P') || (*options
== 'D') || (*options
== 'R')))
10621 if (*options
== 'D') phone_mode
= 2;
10622 ast_set_callerid(chan
,"0","app_rpt user","0");
10624 ast_channel_setoption(chan
,AST_OPTION_TONE_VERIFY
,&val
,sizeof(char),0);
10628 #ifdef ALLOW_LOCAL_CHANNELS
10629 /* Check to insure the connection is IAX2 or Local*/
10630 if ( (strncmp(chan
->name
,"IAX2",4)) && (strncmp(chan
->name
,"Local",5)) ) {
10631 ast_log(LOG_WARNING
, "We only accept links via IAX2 or Local!!\n");
10635 if (strncmp(chan
->name
,"IAX2",4))
10637 ast_log(LOG_WARNING
, "We only accept links via IAX2!!\n");
10642 if (options
&& (*options
== 'R'))
10645 /* Parts of this section taken from app_parkandannounce */
10646 char *return_context
;
10647 int l
, m
, lot
, timeout
= 0;
10648 char tmp
[256],*template;
10649 char *working
, *context
, *exten
, *priority
;
10653 rpt_mutex_lock(&myrpt
->lock
);
10654 m
= myrpt
->callmode
;
10655 rpt_mutex_unlock(&myrpt
->lock
);
10657 if ((!myrpt
->p
.nobusyout
) && m
)
10659 if (chan
->_state
!= AST_STATE_UP
)
10661 ast_indicate(chan
,AST_CONTROL_BUSY
);
10663 while(ast_safe_sleep(chan
,10000) != -1);
10667 if (chan
->_state
!= AST_STATE_UP
)
10672 l
=strlen(options
)+2;
10675 ast_log(LOG_WARNING
, "Out of memory\n");
10679 strncpy(s
,options
,l
);
10681 template=strsep(&s
,"|");
10683 ast_log(LOG_WARNING
, "An announce template must be defined\n");
10689 timeout
= atoi(strsep(&s
, "|"));
10693 return_context
= s
;
10695 if(return_context
!= NULL
) {
10696 /* set the return context. Code borrowed from the Goto builtin */
10698 working
= return_context
;
10699 context
= strsep(&working
, "|");
10700 exten
= strsep(&working
, "|");
10702 /* Only a priority in this one */
10703 priority
= context
;
10707 priority
= strsep(&working
, "|");
10709 /* Only an extension and priority in this one */
10715 if(atoi(priority
) < 0) {
10716 ast_log(LOG_WARNING
, "Priority '%s' must be a number > 0\n", priority
);
10720 /* At this point we have a priority and maybe an extension and a context */
10721 chan
->priority
= atoi(priority
);
10722 #ifdef OLD_ASTERISK
10723 if(exten
&& strcasecmp(exten
, "BYEXTENSION"))
10727 strncpy(chan
->exten
, exten
, sizeof(chan
->exten
)-1);
10729 strncpy(chan
->context
, context
, sizeof(chan
->context
)-1);
10730 } else { /* increment the priority by default*/
10734 if(option_verbose
> 2) {
10735 ast_verbose( VERBOSE_PREFIX_3
"Return Context: (%s,%s,%d) ID: %s\n", chan
->context
,chan
->exten
, chan
->priority
, chan
->cid
.cid_num
);
10736 if(!ast_exists_extension(chan
, chan
->context
, chan
->exten
, chan
->priority
, chan
->cid
.cid_num
)) {
10737 ast_verbose( VERBOSE_PREFIX_3
"Warning: Return Context Invalid, call will return to default|s\n");
10741 /* we are using masq_park here to protect * from touching the channel once we park it. If the channel comes out of timeout
10742 before we are done announcing and the channel is messed with, Kablooeee. So we use Masq to prevent this. */
10744 ast_masq_park_call(chan
, NULL
, timeout
, &lot
);
10746 if (option_verbose
> 2) ast_verbose( VERBOSE_PREFIX_3
"Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot
, timeout
, return_context
);
10748 snprintf(tmp
,sizeof(tmp
) - 1,"%d,%s",lot
,template + 1);
10750 rpt_telemetry(myrpt
,REV_PATCH
,tmp
);
10760 struct ast_hostent ahp
;
10761 struct hostent
*hp
;
10763 char hisip
[100],nodeip
[100],*val
, *s
, *s1
, *s2
, *b
,*b1
;
10765 /* look at callerid to see what node this comes from */
10766 if (!chan
->cid
.cid_num
) /* if doesn't have caller id */
10768 ast_log(LOG_WARNING
, "Doesnt have callerid on %s\n",tmp
);
10772 /* get his IP from IAX2 module */
10773 memset(hisip
,0,sizeof(hisip
));
10774 #ifdef ALLOW_LOCAL_CHANNELS
10775 /* set IP address if this is a local connection*/
10776 if (strncmp(chan
->name
,"Local",5)==0) {
10777 strcpy(hisip
,"127.0.0.1");
10779 pbx_substitute_variables_helper(chan
,"${IAXPEER(CURRENTCHANNEL)}",hisip
,sizeof(hisip
) - 1);
10782 pbx_substitute_variables_helper(chan
,"${IAXPEER(CURRENTCHANNEL)}",hisip
,sizeof(hisip
) - 1);
10787 ast_log(LOG_WARNING
, "Link IP address cannot be determined!!\n");
10791 ast_callerid_parse(chan
->cid
.cid_num
,&b
,&b1
);
10792 ast_shrink_phone_number(b1
);
10793 if (!strcmp(myrpt
->name
,b1
))
10795 ast_log(LOG_WARNING
, "Trying to link to self!!\n");
10801 ast_log(LOG_WARNING
, "Node %s Invalid for connection here!!\n",b1
);
10806 /* look for his reported node string */
10807 val
= node_lookup(myrpt
,b1
);
10810 ast_log(LOG_WARNING
, "Reported node %s cannot be found!!\n",b1
);
10813 strncpy(tmp
,val
,sizeof(tmp
) - 1);
10815 s1
= strsep(&s
,",");
10816 s2
= strsep(&s
,",");
10819 ast_log(LOG_WARNING
, "Reported node %s not in correct format!!\n",b1
);
10822 if (strcmp(s2
,"NONE")) {
10823 hp
= ast_gethostbyname(s2
, &ahp
);
10826 ast_log(LOG_WARNING
, "Reported node %s, name %s cannot be found!!\n",b1
,s2
);
10829 memcpy(&ia
,hp
->h_addr
,sizeof(in_addr_t
));
10830 #ifdef OLD_ASTERISK
10831 ast_inet_ntoa(nodeip
,sizeof(nodeip
) - 1,ia
);
10833 strncpy(nodeip
,ast_inet_ntoa(ia
),sizeof(nodeip
) - 1);
10835 if (strcmp(hisip
,nodeip
))
10837 char *s3
= strchr(s1
,'@');
10838 if (s3
) s1
= s3
+ 1;
10839 s3
= strchr(s1
,'/');
10841 hp
= ast_gethostbyname(s1
, &ahp
);
10844 ast_log(LOG_WARNING
, "Reported node %s, name %s cannot be found!!\n",b1
,s1
);
10847 memcpy(&ia
,hp
->h_addr
,sizeof(in_addr_t
));
10848 #ifdef OLD_ASTERISK
10849 ast_inet_ntoa(nodeip
,sizeof(nodeip
) - 1,ia
);
10851 strncpy(nodeip
,ast_inet_ntoa(ia
),sizeof(nodeip
) - 1);
10853 if (strcmp(hisip
,nodeip
))
10855 ast_log(LOG_WARNING
, "Node %s IP %s does not match link IP %s!!\n",b1
,nodeip
,hisip
);
10862 /* if is not a remote */
10863 if (!myrpt
->remote
)
10867 int reconnects
= 0;
10869 /* look at callerid to see what node this comes from */
10870 if (!chan
->cid
.cid_num
) /* if doesn't have caller id */
10872 ast_log(LOG_WARNING
, "Doesnt have callerid on %s\n",tmp
);
10876 ast_callerid_parse(chan
->cid
.cid_num
,&b
,&b1
);
10877 ast_shrink_phone_number(b1
);
10878 if (!strcmp(myrpt
->name
,b1
))
10880 ast_log(LOG_WARNING
, "Trying to link to self!!\n");
10883 rpt_mutex_lock(&myrpt
->lock
);
10884 l
= myrpt
->links
.next
;
10885 /* try to find this one in queue */
10886 while(l
!= &myrpt
->links
)
10888 if (l
->name
[0] == '0')
10893 /* if found matching string */
10894 if (!strcmp(l
->name
,b1
)) break;
10898 if (l
!= &myrpt
->links
)
10901 l
->retries
= l
->max_retries
+ 1;
10903 reconnects
= l
->reconnects
;
10905 rpt_mutex_unlock(&myrpt
->lock
);
10908 rpt_mutex_unlock(&myrpt
->lock
);
10909 /* establish call in tranceive mode */
10910 l
= malloc(sizeof(struct rpt_link
));
10913 ast_log(LOG_WARNING
, "Unable to malloc\n");
10914 pthread_exit(NULL
);
10916 /* zero the silly thing */
10917 memset((char *)l
,0,sizeof(struct rpt_link
));
10919 strncpy(l
->name
,b1
,MAXNODESTR
- 1);
10923 l
->thisconnected
= 1;
10924 l
->hasconnected
= 1;
10925 l
->reconnects
= reconnects
;
10926 l
->phonemode
= phone_mode
;
10930 ast_set_read_format(l
->chan
,AST_FORMAT_SLINEAR
);
10931 ast_set_write_format(l
->chan
,AST_FORMAT_SLINEAR
);
10932 /* allocate a pseudo-channel thru asterisk */
10933 l
->pchan
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
10936 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
10937 pthread_exit(NULL
);
10939 ast_set_read_format(l
->pchan
,AST_FORMAT_SLINEAR
);
10940 ast_set_write_format(l
->pchan
,AST_FORMAT_SLINEAR
);
10941 #ifdef AST_CDR_FLAG_POST_DISABLED
10942 ast_set_flag(l
->pchan
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
10944 /* make a conference for the tx */
10946 ci
.confno
= myrpt
->conf
;
10947 ci
.confmode
= DAHDI_CONF_CONF
| DAHDI_CONF_LISTENER
| DAHDI_CONF_TALKER
;
10948 /* first put the channel on the conference in proper mode */
10949 if (ioctl(l
->pchan
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
10951 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
10952 pthread_exit(NULL
);
10954 rpt_mutex_lock(&myrpt
->lock
);
10955 if (phone_mode
> 1) l
->lastrx
= 1;
10956 l
->max_retries
= MAX_RETRIES
;
10957 /* insert at end of queue */
10958 insque((struct qelem
*)l
,(struct qelem
*)myrpt
->links
.next
);
10959 __kickshort(myrpt
);
10960 rpt_mutex_unlock(&myrpt
->lock
);
10961 if (chan
->_state
!= AST_STATE_UP
) {
10964 if (myrpt
->p
.archivedir
)
10969 sprintf(str
,"LINK(P),%s",l
->name
);
10971 sprintf(str
,"LINK,%s",l
->name
);
10972 donodelog(myrpt
,str
);
10974 return AST_PBX_KEEPALIVE
;
10976 /* well, then it is a remote */
10977 rpt_mutex_lock(&myrpt
->lock
);
10978 /* if remote, error if anyone else already linked */
10979 if (myrpt
->remoteon
)
10981 rpt_mutex_unlock(&myrpt
->lock
);
10983 if (myrpt
->remoteon
)
10985 ast_log(LOG_WARNING
, "Trying to use busy link on %s\n",tmp
);
10988 rpt_mutex_lock(&myrpt
->lock
);
10990 if ((!strcmp(myrpt
->remote
, remote_rig_rbi
)) &&
10991 (ioperm(myrpt
->p
.iobase
,1,1) == -1))
10993 rpt_mutex_unlock(&myrpt
->lock
);
10994 ast_log(LOG_WARNING
, "Cant get io permission on IO port %x hex\n",myrpt
->p
.iobase
);
10997 myrpt
->remoteon
= 1;
10998 #ifdef OLD_ASTERISK
11001 rpt_mutex_unlock(&myrpt
->lock
);
11002 /* find our index, and load the vars initially */
11003 for(i
= 0; i
< nrpts
; i
++)
11005 if (&rpt_vars
[i
] == myrpt
)
11007 load_rpt_vars(i
,0);
11011 rpt_mutex_lock(&myrpt
->lock
);
11012 tele
= strchr(myrpt
->rxchanname
,'/');
11015 fprintf(stderr
,"rpt:Dial number must be in format tech/number\n");
11016 rpt_mutex_unlock(&myrpt
->lock
);
11017 pthread_exit(NULL
);
11020 myrpt
->rxchannel
= ast_request(myrpt
->rxchanname
,AST_FORMAT_SLINEAR
,tele
,NULL
);
11021 myrpt
->zaprxchannel
= NULL
;
11022 if (!strcasecmp(myrpt
->rxchanname
,"Zap"))
11023 myrpt
->zaprxchannel
= myrpt
->rxchannel
;
11024 if (myrpt
->rxchannel
)
11026 ast_set_read_format(myrpt
->rxchannel
,AST_FORMAT_SLINEAR
);
11027 ast_set_write_format(myrpt
->rxchannel
,AST_FORMAT_SLINEAR
);
11028 #ifdef AST_CDR_FLAG_POST_DISABLED
11029 ast_set_flag(myrpt
->rxchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
11031 myrpt
->rxchannel
->whentohangup
= 0;
11032 myrpt
->rxchannel
->appl
= "Apprpt";
11033 myrpt
->rxchannel
->data
= "(Link Rx)";
11034 if (option_verbose
> 2)
11035 ast_verbose(VERBOSE_PREFIX_3
"rpt (Rx) initiating call to %s/%s on %s\n",
11036 myrpt
->rxchanname
,tele
,myrpt
->rxchannel
->name
);
11037 rpt_mutex_unlock(&myrpt
->lock
);
11038 ast_call(myrpt
->rxchannel
,tele
,999);
11039 rpt_mutex_lock(&myrpt
->lock
);
11043 fprintf(stderr
,"rpt:Sorry unable to obtain Rx channel\n");
11044 rpt_mutex_unlock(&myrpt
->lock
);
11045 pthread_exit(NULL
);
11048 myrpt
->zaptxchannel
= NULL
;
11049 if (myrpt
->txchanname
)
11051 tele
= strchr(myrpt
->txchanname
,'/');
11054 fprintf(stderr
,"rpt:Dial number must be in format tech/number\n");
11055 rpt_mutex_unlock(&myrpt
->lock
);
11056 ast_hangup(myrpt
->rxchannel
);
11057 pthread_exit(NULL
);
11060 myrpt
->txchannel
= ast_request(myrpt
->txchanname
,AST_FORMAT_SLINEAR
,tele
,NULL
);
11061 if (!strcasecmp(myrpt
->txchanname
,"Zap"))
11062 myrpt
->zaptxchannel
= myrpt
->txchannel
;
11063 if (myrpt
->txchannel
)
11065 ast_set_read_format(myrpt
->txchannel
,AST_FORMAT_SLINEAR
);
11066 ast_set_write_format(myrpt
->txchannel
,AST_FORMAT_SLINEAR
);
11067 #ifdef AST_CDR_FLAG_POST_DISABLED
11068 ast_set_flag(myrpt
->txchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
11070 myrpt
->txchannel
->whentohangup
= 0;
11071 myrpt
->txchannel
->appl
= "Apprpt";
11072 myrpt
->txchannel
->data
= "(Link Tx)";
11073 if (option_verbose
> 2)
11074 ast_verbose(VERBOSE_PREFIX_3
"rpt (Tx) initiating call to %s/%s on %s\n",
11075 myrpt
->txchanname
,tele
,myrpt
->txchannel
->name
);
11076 rpt_mutex_unlock(&myrpt
->lock
);
11077 ast_call(myrpt
->txchannel
,tele
,999);
11078 rpt_mutex_lock(&myrpt
->lock
);
11082 fprintf(stderr
,"rpt:Sorry unable to obtain Tx channel\n");
11083 rpt_mutex_unlock(&myrpt
->lock
);
11084 ast_hangup(myrpt
->rxchannel
);
11085 pthread_exit(NULL
);
11091 myrpt
->txchannel
= myrpt
->rxchannel
;
11093 /* allocate a pseudo-channel thru asterisk */
11094 myrpt
->pchannel
= ast_request("zap",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
11095 if (!myrpt
->pchannel
)
11097 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
11098 rpt_mutex_unlock(&myrpt
->lock
);
11099 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
11100 ast_hangup(myrpt
->txchannel
);
11101 ast_hangup(myrpt
->rxchannel
);
11102 pthread_exit(NULL
);
11104 ast_set_read_format(myrpt
->pchannel
,AST_FORMAT_SLINEAR
);
11105 ast_set_write_format(myrpt
->pchannel
,AST_FORMAT_SLINEAR
);
11106 #ifdef AST_CDR_FLAG_POST_DISABLED
11107 ast_set_flag(myrpt
->pchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
11109 if (!myrpt
->zaprxchannel
) myrpt
->zaprxchannel
= myrpt
->pchannel
;
11110 if (!myrpt
->zaptxchannel
) myrpt
->zaptxchannel
= myrpt
->pchannel
;
11111 /* make a conference for the pseudo */
11113 ci
.confno
= -1; /* make a new conf */
11114 ci
.confmode
= DAHDI_CONF_CONFANNMON
;
11115 /* first put the channel on the conference in announce/monitor mode */
11116 if (ioctl(myrpt
->pchannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
11118 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
11119 rpt_mutex_unlock(&myrpt
->lock
);
11120 ast_hangup(myrpt
->pchannel
);
11121 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
11122 ast_hangup(myrpt
->txchannel
);
11123 ast_hangup(myrpt
->rxchannel
);
11124 pthread_exit(NULL
);
11126 /* save pseudo channel conference number */
11127 myrpt
->conf
= myrpt
->txconf
= ci
.confno
;
11128 /* if serial io port, open it */
11130 if (myrpt
->p
.ioport
&& ((myrpt
->iofd
= openserial(myrpt
->p
.ioport
)) == -1))
11132 rpt_mutex_unlock(&myrpt
->lock
);
11133 ast_hangup(myrpt
->pchannel
);
11134 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
11135 ast_hangup(myrpt
->txchannel
);
11136 ast_hangup(myrpt
->rxchannel
);
11137 pthread_exit(NULL
);
11139 iskenwood_pci4
= 0;
11140 memset(&z
,0,sizeof(z
));
11141 if ((myrpt
->iofd
< 1) && (myrpt
->txchannel
== myrpt
->zaptxchannel
))
11143 z
.radpar
= DAHDI_RADPAR_REMMODE
;
11144 z
.data
= DAHDI_RADPAR_REM_NONE
;
11145 res
= ioctl(myrpt
->zaptxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&z
);
11146 /* if PCIRADIO and kenwood selected */
11147 if ((!res
) && (!strcmp(myrpt
->remote
,remote_rig_kenwood
)))
11149 z
.radpar
= DAHDI_RADPAR_UIOMODE
;
11151 if (ioctl(myrpt
->zaptxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&z
) == -1)
11153 ast_log(LOG_ERROR
,"Cannot set UIOMODE\n");
11156 z
.radpar
= DAHDI_RADPAR_UIODATA
;
11158 if (ioctl(myrpt
->zaptxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&z
) == -1)
11160 ast_log(LOG_ERROR
,"Cannot set UIODATA\n");
11164 if (ioctl(myrpt
->zaptxchannel
->fds
[0],DAHDI_HOOK
,&i
) == -1)
11166 ast_log(LOG_ERROR
,"Cannot set hook\n");
11169 iskenwood_pci4
= 1;
11172 if (myrpt
->txchannel
== myrpt
->zaptxchannel
)
11175 ioctl(myrpt
->zaptxchannel
->fds
[0],DAHDI_HOOK
,&i
);
11176 /* if PCIRADIO and Yaesu ft897/ICOM IC-706 selected */
11177 if ((myrpt
->iofd
< 1) && (!res
) &&
11178 (!strcmp(myrpt
->remote
,remote_rig_ft897
) ||
11179 (!strcmp(myrpt
->remote
,remote_rig_ic706
))))
11181 z
.radpar
= DAHDI_RADPAR_UIOMODE
;
11183 if (ioctl(myrpt
->zaptxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&z
) == -1)
11185 ast_log(LOG_ERROR
,"Cannot set UIOMODE\n");
11188 z
.radpar
= DAHDI_RADPAR_UIODATA
;
11190 if (ioctl(myrpt
->zaptxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&z
) == -1)
11192 ast_log(LOG_ERROR
,"Cannot set UIODATA\n");
11197 myrpt
->remoterx
= 0;
11198 myrpt
->remotetx
= 0;
11199 myrpt
->retxtimer
= 0;
11200 myrpt
->rerxtimer
= 0;
11201 myrpt
->remoteon
= 1;
11202 myrpt
->dtmfidx
= -1;
11203 myrpt
->dtmfbuf
[0] = 0;
11204 myrpt
->dtmf_time_rem
= 0;
11205 myrpt
->hfscanmode
= 0;
11206 myrpt
->hfscanstatus
= 0;
11207 if (myrpt
->p
.startupmacro
)
11209 snprintf(myrpt
->macrobuf
,MAXMACRO
- 1,"PPPP%s",myrpt
->p
.startupmacro
);
11211 time(&myrpt
->start_time
);
11212 myrpt
->last_activity_time
= myrpt
->start_time
;
11213 last_timeout_warning
= 0;
11215 myrpt
->tele
.next
= &myrpt
->tele
;
11216 myrpt
->tele
.prev
= &myrpt
->tele
;
11217 rpt_mutex_unlock(&myrpt
->lock
);
11218 ast_set_write_format(chan
, AST_FORMAT_SLINEAR
);
11219 ast_set_read_format(chan
, AST_FORMAT_SLINEAR
);
11222 /* if we are on 2w loop and are a remote, turn EC on */
11223 if (myrpt
->remote
&& (myrpt
->rxchannel
== myrpt
->txchannel
))
11226 ioctl(myrpt
->zaprxchannel
->fds
[0],DAHDI_ECHOCANCEL
,&i
);
11228 if (chan
->_state
!= AST_STATE_UP
) {
11232 if (myrpt
->rxchannel
== myrpt
->zaprxchannel
)
11234 if (ioctl(myrpt
->zaprxchannel
->fds
[0],DAHDI_GET_PARAMS
,&par
) != -1)
11236 if (par
.rxisoffhook
)
11238 ast_indicate(chan
,AST_CONTROL_RADIO_KEY
);
11239 myrpt
->remoterx
= 1;
11244 if (myrpt
->p
.archivedir
)
11246 char mycmd
[100],mydate
[100],*b
,*b1
;
11251 mkdir(myrpt
->p
.archivedir
,0600);
11252 sprintf(mycmd
,"%s/%s",myrpt
->p
.archivedir
,myrpt
->name
);
11255 strftime(mydate
,sizeof(mydate
) - 1,"%Y%m%d%H%M%S",
11257 sprintf(mycmd
,"mixmonitor start %s %s/%s/%s.wav49 a",chan
->name
,
11258 myrpt
->p
.archivedir
,myrpt
->name
,mydate
);
11259 if (myrpt
->p
.monminblocks
)
11261 blocksleft
= diskavail(myrpt
);
11262 if (myrpt
->p
.remotetimeout
)
11264 blocksleft
-= (myrpt
->p
.remotetimeout
*
11265 MONITOR_DISK_BLOCKS_PER_MINUTE
) / 60;
11267 if (blocksleft
>= myrpt
->p
.monminblocks
)
11268 ast_cli_command(nullfd
,mycmd
);
11269 } else ast_cli_command(nullfd
,mycmd
);
11270 /* look at callerid to see what node this comes from */
11271 if (!chan
->cid
.cid_num
) /* if doesn't have caller id */
11275 ast_callerid_parse(chan
->cid
.cid_num
,&b
,&b1
);
11276 ast_shrink_phone_number(b1
);
11278 sprintf(mycmd
,"CONNECT,%s",b1
);
11279 donodelog(myrpt
,mycmd
);
11281 myrpt
->loginuser
[0] = 0;
11282 myrpt
->loginlevel
[0] = 0;
11283 myrpt
->authtelltimer
= 0;
11284 myrpt
->authtimer
= 0;
11287 if (myrpt
->p
.authlevel
> 1) authreq
= 1;
11292 cs
[n
++] = myrpt
->rxchannel
;
11293 cs
[n
++] = myrpt
->pchannel
;
11294 if (myrpt
->rxchannel
!= myrpt
->txchannel
)
11295 cs
[n
++] = myrpt
->txchannel
;
11296 /* start un-locked */
11299 if (ast_check_hangup(chan
)) break;
11300 if (ast_check_hangup(myrpt
->rxchannel
)) break;
11304 telem
= myrpt
->tele
.next
;
11305 while(telem
!= &myrpt
->tele
)
11307 if (telem
->mode
== SETREMOTE
) setting
= 1;
11308 if ((telem
->mode
== SETREMOTE
) ||
11309 (telem
->mode
== SCAN
) ||
11310 (telem
->mode
== TUNE
)) reming
= 1;
11311 else notremming
= 1;
11312 telem
= telem
->next
;
11317 /* find our index, and load the vars */
11318 for(i
= 0; i
< nrpts
; i
++)
11320 if (&rpt_vars
[i
] == myrpt
)
11322 load_rpt_vars(i
,0);
11328 if (myrpt
->p
.remotetimeout
)
11332 r
= (t
- myrpt
->start_time
);
11333 if (r
>= myrpt
->p
.remotetimeout
)
11335 sayfile(chan
,"rpt/node");
11336 ast_say_character_str(chan
,myrpt
->name
,NULL
,chan
->language
);
11337 sayfile(chan
,"rpt/timeout");
11338 ast_safe_sleep(chan
,1000);
11341 if ((myrpt
->p
.remotetimeoutwarning
) &&
11342 (r
>= (myrpt
->p
.remotetimeout
-
11343 myrpt
->p
.remotetimeoutwarning
)) &&
11344 (r
<= (myrpt
->p
.remotetimeout
-
11345 myrpt
->p
.remotetimeoutwarningfreq
)))
11347 if (myrpt
->p
.remotetimeoutwarningfreq
)
11349 if ((t
- last_timeout_warning
) >=
11350 myrpt
->p
.remotetimeoutwarningfreq
)
11352 time(&last_timeout_warning
);
11353 rpt_telemetry(myrpt
,TIMEOUT_WARNING
,0);
11358 if (!last_timeout_warning
)
11360 time(&last_timeout_warning
);
11361 rpt_telemetry(myrpt
,TIMEOUT_WARNING
,0);
11366 if (myrpt
->p
.remoteinacttimeout
&& myrpt
->last_activity_time
)
11370 r
= (t
- myrpt
->last_activity_time
);
11371 if (r
>= myrpt
->p
.remoteinacttimeout
)
11373 sayfile(chan
,"rpt/node");
11374 ast_say_character_str(chan
,myrpt
->name
,NULL
,chan
->language
);
11375 sayfile(chan
,"rpt/timeout");
11376 ast_safe_sleep(chan
,1000);
11379 if ((myrpt
->p
.remotetimeoutwarning
) &&
11380 (r
>= (myrpt
->p
.remoteinacttimeout
-
11381 myrpt
->p
.remotetimeoutwarning
)) &&
11382 (r
<= (myrpt
->p
.remoteinacttimeout
-
11383 myrpt
->p
.remotetimeoutwarningfreq
)))
11385 if (myrpt
->p
.remotetimeoutwarningfreq
)
11387 if ((t
- last_timeout_warning
) >=
11388 myrpt
->p
.remotetimeoutwarningfreq
)
11390 time(&last_timeout_warning
);
11391 rpt_telemetry(myrpt
,ACT_TIMEOUT_WARNING
,0);
11396 if (!last_timeout_warning
)
11398 time(&last_timeout_warning
);
11399 rpt_telemetry(myrpt
,ACT_TIMEOUT_WARNING
,0);
11405 who
= ast_waitfor_n(cs
,n
,&ms
);
11406 if (who
== NULL
) ms
= 0;
11407 elap
= MSWAIT
- ms
;
11408 if (myrpt
->macrotimer
) myrpt
->macrotimer
-= elap
;
11409 if (myrpt
->macrotimer
< 0) myrpt
->macrotimer
= 0;
11411 /* do local dtmf timer */
11412 if (myrpt
->dtmf_local_timer
)
11414 if (myrpt
->dtmf_local_timer
> 1) myrpt
->dtmf_local_timer
-= elap
;
11415 if (myrpt
->dtmf_local_timer
< 1) myrpt
->dtmf_local_timer
= 1;
11417 rpt_mutex_lock(&myrpt
->lock
);
11418 do_dtmf_local(myrpt
,0);
11419 rpt_mutex_unlock(&myrpt
->lock
);
11420 rem_totx
= myrpt
->dtmf_local_timer
&& (!phone_mode
);
11421 rem_totx
|= keyed
&& (!myrpt
->tunerequest
);
11422 rem_rx
= (remkeyed
&& (!setting
)) || (myrpt
->tele
.next
!= &myrpt
->tele
);
11423 if(!strcmp(myrpt
->remote
, remote_rig_ic706
))
11424 rem_totx
|= myrpt
->tunerequest
;
11425 if (keyed
&& (!keyed1
))
11430 if (!keyed
&& (keyed1
))
11436 /* if login necessary, and not too soon */
11437 if ((myrpt
->p
.authlevel
) &&
11438 (!myrpt
->loginlevel
[0]) &&
11443 myrpt
->authtelltimer
= AUTHTELLTIME
- AUTHTXTIME
;
11448 if (rem_rx
&& (!myrpt
->remoterx
))
11450 myrpt
->remoterx
= 1;
11451 ast_indicate(chan
,AST_CONTROL_RADIO_KEY
);
11453 if ((!rem_rx
) && (myrpt
->remoterx
))
11455 myrpt
->remoterx
= 0;
11456 ast_indicate(chan
,AST_CONTROL_RADIO_UNKEY
);
11458 /* if auth requested, and not authed yet */
11459 if (authreq
&& (!myrpt
->loginlevel
[0]))
11461 if ((!authtold
) && ((myrpt
->authtelltimer
+= elap
)
11465 rpt_telemetry(myrpt
,LOGINREQ
,NULL
);
11467 if ((myrpt
->authtimer
+= elap
) >= AUTHLOGOUTTIME
)
11469 break; /* if not logged in, hang up after a time */
11473 if ((myrpt
->retxtimer
+= elap
) >= REDUNDANT_TX_TIME
)
11475 myrpt
->retxtimer
= 0;
11476 if ((myrpt
->remoterx
) && (!myrpt
->remotetx
))
11477 ast_indicate(chan
,AST_CONTROL_RADIO_KEY
);
11479 ast_indicate(chan
,AST_CONTROL_RADIO_UNKEY
);
11482 if ((myrpt
->rerxtimer
+= elap
) >= (REDUNDANT_TX_TIME
* 2))
11485 myrpt
->rerxtimer
= 0;
11488 if (rem_totx
&& (!myrpt
->remotetx
))
11490 /* if not authed, and needed, dont transmit */
11491 if ((!myrpt
->p
.authlevel
) || myrpt
->loginlevel
[0])
11493 myrpt
->remotetx
= 1;
11494 if((myrpt
->remtxfreqok
= check_tx_freq(myrpt
)))
11496 time(&myrpt
->last_activity_time
);
11497 if ((iskenwood_pci4
) && (myrpt
->txchannel
== myrpt
->zaptxchannel
))
11499 z
.radpar
= DAHDI_RADPAR_UIODATA
;
11501 if (ioctl(myrpt
->zaptxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&z
) == -1)
11503 ast_log(LOG_ERROR
,"Cannot set UIODATA\n");
11509 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_KEY
);
11511 if (myrpt
->p
.archivedir
) donodelog(myrpt
,"TXKEY");
11515 if ((!rem_totx
) && myrpt
->remotetx
) /* Remote base radio TX unkey */
11517 myrpt
->remotetx
= 0;
11518 if(!myrpt
->remtxfreqok
){
11519 rpt_telemetry(myrpt
,UNAUTHTX
,NULL
);
11521 if ((iskenwood_pci4
) && (myrpt
->txchannel
== myrpt
->zaptxchannel
))
11523 z
.radpar
= DAHDI_RADPAR_UIODATA
;
11525 if (ioctl(myrpt
->zaptxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&z
) == -1)
11527 ast_log(LOG_ERROR
,"Cannot set UIODATA\n");
11533 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_UNKEY
);
11535 if (myrpt
->p
.archivedir
) donodelog(myrpt
,"TXUNKEY");
11537 if (myrpt
->hfscanmode
){
11538 myrpt
->scantimer
-= elap
;
11539 if(myrpt
->scantimer
<= 0){
11542 myrpt
->scantimer
= REM_SCANTIME
;
11543 rpt_telemetry(myrpt
,SCAN
,0);
11544 } else myrpt
->scantimer
= 1;
11547 rpt_mutex_lock(&myrpt
->lock
);
11548 c
= myrpt
->macrobuf
[0];
11549 if (c
&& (!myrpt
->macrotimer
))
11551 myrpt
->macrotimer
= MACROTIME
;
11552 memmove(myrpt
->macrobuf
,myrpt
->macrobuf
+ 1,MAXMACRO
- 1);
11553 if ((c
== 'p') || (c
== 'P'))
11554 myrpt
->macrotimer
= MACROPTIME
;
11555 rpt_mutex_unlock(&myrpt
->lock
);
11556 if (myrpt
->p
.archivedir
)
11559 sprintf(str
,"DTMF(M),%c",c
);
11560 donodelog(myrpt
,str
);
11562 if (handle_remote_dtmf_digit(myrpt
,c
,&keyed
,0) == -1) break;
11564 } else rpt_mutex_unlock(&myrpt
->lock
);
11565 if (who
== chan
) /* if it was a read from incomming */
11567 f
= ast_read(chan
);
11570 if (debug
) printf("@@@@ link:Hung Up\n");
11573 if (f
->frametype
== AST_FRAME_VOICE
)
11575 if (ioctl(chan
->fds
[0], DAHDI_GETCONFMUTE
, &ismuted
) == -1)
11579 /* if not transmitting, zero-out audio */
11580 ismuted
|= (!myrpt
->remotetx
);
11581 if (dtmfed
&& phone_mode
) ismuted
= 1;
11585 memset(f
->data
,0,f
->datalen
);
11587 memset(myrpt
->lastf1
->data
,0,myrpt
->lastf1
->datalen
);
11589 memset(myrpt
->lastf2
->data
,0,myrpt
->lastf2
->datalen
);
11591 if (f
) f2
= ast_frdup(f
);
11593 f1
= myrpt
->lastf2
;
11594 myrpt
->lastf2
= myrpt
->lastf1
;
11595 myrpt
->lastf1
= f2
;
11599 memset(myrpt
->lastf1
->data
,0,myrpt
->lastf1
->datalen
);
11601 memset(myrpt
->lastf2
->data
,0,myrpt
->lastf2
->datalen
);
11606 ast_write(myrpt
->txchannel
,f1
);
11608 ast_write(myrpt
->txchannel
,f
);
11612 #ifndef OLD_ASTERISK
11613 else if (f
->frametype
== AST_FRAME_DTMF_BEGIN
)
11616 memset(myrpt
->lastf1
->data
,0,myrpt
->lastf1
->datalen
);
11618 memset(myrpt
->lastf2
->data
,0,myrpt
->lastf2
->datalen
);
11622 if (f
->frametype
== AST_FRAME_DTMF
)
11625 memset(myrpt
->lastf1
->data
,0,myrpt
->lastf1
->datalen
);
11627 memset(myrpt
->lastf2
->data
,0,myrpt
->lastf2
->datalen
);
11629 if (handle_remote_phone_dtmf(myrpt
,f
->subclass
,&keyed
,phone_mode
) == -1)
11631 if (debug
) printf("@@@@ rpt:Hung Up\n");
11636 if (f
->frametype
== AST_FRAME_TEXT
)
11638 if (handle_remote_data(myrpt
,f
->data
) == -1)
11640 if (debug
) printf("@@@@ rpt:Hung Up\n");
11645 if (f
->frametype
== AST_FRAME_CONTROL
)
11647 if (f
->subclass
== AST_CONTROL_HANGUP
)
11649 if (debug
) printf("@@@@ rpt:Hung Up\n");
11654 if (f
->subclass
== AST_CONTROL_RADIO_KEY
)
11656 if (debug
== 7) printf("@@@@ rx key\n");
11658 myrpt
->rerxtimer
= 0;
11661 if (f
->subclass
== AST_CONTROL_RADIO_UNKEY
)
11663 myrpt
->rerxtimer
= 0;
11664 if (debug
== 7) printf("@@@@ rx un-key\n");
11671 if (who
== myrpt
->rxchannel
) /* if it was a read from radio */
11673 f
= ast_read(myrpt
->rxchannel
);
11676 if (debug
) printf("@@@@ link:Hung Up\n");
11679 if (f
->frametype
== AST_FRAME_VOICE
)
11683 if(!strcmp(myrpt
->remote
, remote_rig_kenwood
))
11686 if (myreming
|| (!remkeyed
) ||
11687 ((myrpt
->remote
) && (myrpt
->remotetx
)) ||
11688 ((myrpt
->remmode
!= REM_MODE_FM
) &&
11690 memset(f
->data
,0,f
->datalen
);
11691 ast_write(myrpt
->pchannel
,f
);
11693 else if (f
->frametype
== AST_FRAME_CONTROL
)
11695 if (f
->subclass
== AST_CONTROL_HANGUP
)
11697 if (debug
) printf("@@@@ rpt:Hung Up\n");
11702 if (f
->subclass
== AST_CONTROL_RADIO_KEY
)
11704 if (debug
== 7) printf("@@@@ remote rx key\n");
11705 if (!myrpt
->remotetx
)
11711 if (f
->subclass
== AST_CONTROL_RADIO_UNKEY
)
11713 if (debug
== 7) printf("@@@@ remote rx un-key\n");
11714 if (!myrpt
->remotetx
)
11723 if (who
== myrpt
->pchannel
) /* if is remote mix output */
11725 f
= ast_read(myrpt
->pchannel
);
11728 if (debug
) printf("@@@@ link:Hung Up\n");
11731 if (f
->frametype
== AST_FRAME_VOICE
)
11735 if (f
->frametype
== AST_FRAME_CONTROL
)
11737 if (f
->subclass
== AST_CONTROL_HANGUP
)
11739 if (debug
) printf("@@@@ rpt:Hung Up\n");
11747 if ((myrpt
->rxchannel
!= myrpt
->txchannel
) &&
11748 (who
== myrpt
->txchannel
)) /* do this cuz you have to */
11750 f
= ast_read(myrpt
->txchannel
);
11753 if (debug
) printf("@@@@ link:Hung Up\n");
11756 if (f
->frametype
== AST_FRAME_CONTROL
)
11758 if (f
->subclass
== AST_CONTROL_HANGUP
)
11760 if (debug
) printf("@@@@ rpt:Hung Up\n");
11769 if (myrpt
->p
.archivedir
)
11771 char mycmd
[100],*b
,*b1
;
11773 /* look at callerid to see what node this comes from */
11774 if (!chan
->cid
.cid_num
) /* if doesn't have caller id */
11778 ast_callerid_parse(chan
->cid
.cid_num
,&b
,&b1
);
11779 ast_shrink_phone_number(b1
);
11781 sprintf(mycmd
,"DISCONNECT,%s",b1
);
11782 donodelog(myrpt
,mycmd
);
11784 /* wait for telem to be done */
11785 while(myrpt
->tele
.next
!= &myrpt
->tele
) usleep(100000);
11786 sprintf(tmp
,"mixmonitor stop %s",chan
->name
);
11787 ast_cli_command(nullfd
,tmp
);
11789 rpt_mutex_lock(&myrpt
->lock
);
11790 myrpt
->hfscanmode
= 0;
11791 myrpt
->hfscanstatus
= 0;
11792 myrpt
->remoteon
= 0;
11793 rpt_mutex_unlock(&myrpt
->lock
);
11794 if (myrpt
->lastf1
) ast_frfree(myrpt
->lastf1
);
11795 myrpt
->lastf1
= NULL
;
11796 if (myrpt
->lastf2
) ast_frfree(myrpt
->lastf2
);
11797 myrpt
->lastf2
= NULL
;
11798 if ((iskenwood_pci4
) && (myrpt
->txchannel
== myrpt
->zaptxchannel
))
11800 z
.radpar
= DAHDI_RADPAR_UIOMODE
;
11802 if (ioctl(myrpt
->zaptxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&z
) == -1)
11804 ast_log(LOG_ERROR
,"Cannot set UIOMODE\n");
11807 z
.radpar
= DAHDI_RADPAR_UIODATA
;
11809 if (ioctl(myrpt
->zaptxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&z
) == -1)
11811 ast_log(LOG_ERROR
,"Cannot set UIODATA\n");
11815 if (ioctl(myrpt
->zaptxchannel
->fds
[0],DAHDI_HOOK
,&i
) == -1)
11817 ast_log(LOG_ERROR
,"Cannot set hook\n");
11821 if (myrpt
->iofd
) close(myrpt
->iofd
);
11823 ast_hangup(myrpt
->pchannel
);
11824 if (myrpt
->rxchannel
!= myrpt
->txchannel
) ast_hangup(myrpt
->txchannel
);
11825 ast_hangup(myrpt
->rxchannel
);
11827 #ifdef OLD_ASTERISK
11828 LOCAL_USER_REMOVE(u
);
11833 #ifdef OLD_ASTERISK
11834 int unload_module()
11836 static int unload_module(void)
11841 #ifdef OLD_ASTERISK
11842 STANDARD_HANGUP_LOCALUSERS
;
11844 for(i
= 0; i
< nrpts
; i
++) {
11845 if (!strcmp(rpt_vars
[i
].name
,rpt_vars
[i
].p
.nodes
)) continue;
11846 ast_mutex_destroy(&rpt_vars
[i
].lock
);
11847 ast_mutex_destroy(&rpt_vars
[i
].remlock
);
11849 i
= ast_unregister_application(app
);
11851 /* Unregister cli extensions */
11852 ast_cli_unregister(&cli_debug
);
11853 ast_cli_unregister(&cli_dump
);
11854 ast_cli_unregister(&cli_stats
);
11855 ast_cli_unregister(&cli_lstats
);
11856 ast_cli_unregister(&cli_nodes
);
11857 ast_cli_unregister(&cli_reload
);
11858 ast_cli_unregister(&cli_restart
);
11859 ast_cli_unregister(&cli_fun
);
11864 #ifdef OLD_ASTERISK
11867 static int load_module(void)
11870 ast_pthread_create(&rpt_master_thread
,NULL
,rpt_master
,NULL
);
11872 /* Register cli extensions */
11873 ast_cli_register(&cli_debug
);
11874 ast_cli_register(&cli_dump
);
11875 ast_cli_register(&cli_stats
);
11876 ast_cli_register(&cli_lstats
);
11877 ast_cli_register(&cli_nodes
);
11878 ast_cli_register(&cli_reload
);
11879 ast_cli_register(&cli_restart
);
11880 ast_cli_register(&cli_fun
);
11882 return ast_register_application(app
, rpt_exec
, synopsis
, descrip
);
11885 #ifdef OLD_ASTERISK
11886 char *description()
11893 STANDARD_USECOUNT(res
);
11899 return ASTERISK_GPL_KEY
;
11903 #ifdef OLD_ASTERISK
11906 static int reload(void)
11911 for(n
= 0; n
< nrpts
; n
++) rpt_vars
[n
].reload
= 1;
11915 #ifndef OLD_ASTERISK
11916 /* STD_MOD(MOD_1, reload, NULL, NULL); */
11917 AST_MODULE_INFO(ASTERISK_GPL_KEY
, AST_MODFLAG_DEFAULT
, "Radio Repeater/Remote Base Application",
11918 .load
= load_module
,
11919 .unload
= unload_module
,