Skip to content

Commit 05f783c

Browse files
committed
app_hookstate: Add trivial hook-state manipulation applications.
Add applications to take a DAHDI channel on or off-hook to allow for direct hook-state manipulation, as well as a higher-level wrapper application to perform a standard supervision test.
1 parent d809de0 commit 05f783c

File tree

3 files changed

+207
-0
lines changed

3 files changed

+207
-0
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ PhreakScript installs:
6060
- ``PlayDigits``
6161
- ``StreamSilence``
6262
- ``RevertivePulse``
63+
- ``OnHook``
64+
- ``OffHook``
65+
- ``SupervisionTest``
6366
- ``SendFrame``
6467
- ``WaitForFrame``
6568
- ``WaitForDeposit``

apps/app_hookstate.c

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
/*
2+
* Asterisk -- An open source telephony toolkit.
3+
*
4+
* Copyright (C) 2025, Naveen Albert
5+
*
6+
* Naveen Albert <[email protected]>
7+
*
8+
* See http://www.asterisk.org for more information about
9+
* the Asterisk project. Please do not directly contact
10+
* any of the maintainers of this project for assistance;
11+
* the project provides a web site, mailing lists and IRC
12+
* channels for your use.
13+
*
14+
* This program is free software, distributed under the terms of
15+
* the GNU General Public License Version 2. See the LICENSE file
16+
* at the top of the source tree.
17+
*/
18+
19+
/*! \file
20+
*
21+
* \brief DAHDI channel supervision applications
22+
*
23+
* \author Naveen Albert <[email protected]>
24+
*
25+
* \ingroup applications
26+
*/
27+
28+
/*** MODULEINFO
29+
<depend>dahdi</depend>
30+
<support_level>extended</support_level>
31+
***/
32+
33+
#include "asterisk.h"
34+
35+
#include <dahdi/user.h>
36+
37+
#include "asterisk/lock.h"
38+
#include "asterisk/channel.h"
39+
#include "asterisk/pbx.h"
40+
#include "asterisk/module.h"
41+
42+
/*** DOCUMENTATION
43+
<application name="OnHook" language="en_US">
44+
<synopsis>
45+
Go on-hook on a DAHDI channel
46+
</synopsis>
47+
<syntax />
48+
<description>
49+
<para>Go on-hook on a DAHDI channel.</para>
50+
<para>Only works on FXS-signaled channels (FXO ports).</para>
51+
</description>
52+
<see-also>
53+
<ref type="application">OffHook</ref>
54+
<ref type="application">SupervisionTest</ref>
55+
</see-also>
56+
</application>
57+
<application name="OffHook" language="en_US">
58+
<synopsis>
59+
Go off-hook on a DAHDI channel
60+
</synopsis>
61+
<syntax />
62+
<description>
63+
<para>Go off-hook on a DAHDI channel.</para>
64+
<para>Only works on FXS-signaled channels (FXO ports).</para>
65+
</description>
66+
<see-also>
67+
<ref type="application">OnHook</ref>
68+
<ref type="application">SupervisionTest</ref>
69+
</see-also>
70+
</application>
71+
<application name="SupervisionTest" language="en_US">
72+
<synopsis>
73+
Perform a supervision test
74+
</synopsis>
75+
<syntax />
76+
<description>
77+
<para>Run a supervision test on the channel. This will make the channel go on and off-hook alternately.</para>
78+
<para>The supervision test will run indefinitely, until the caller hangs up.</para>
79+
<para>Only works on FXS-signaled channels (FXO ports). To set up an access line, you will want to
80+
tie this to an FXS port (FXO-signaled) and use that as the test number.</para>
81+
<para>The FXS port should be configured with usecallerid=no, calledsubscriberheld=yes, threewaycalling=no, dialmode=none.
82+
The FXO port just needs to call this application.</para>
83+
</description>
84+
<see-also>
85+
<ref type="application">OnHook</ref>
86+
<ref type="application">OffHook</ref>
87+
</see-also>
88+
</application>
89+
***/
90+
91+
static char *app_onhook = "OnHook";
92+
static char *app_offhook = "OffHook";
93+
static char *app_supetest = "SupervisionTest";
94+
95+
static inline int dahdi_wait_event(int fd)
96+
{
97+
/* Avoid the silly dahdi_waitevent which ignores a bunch of events */
98+
int i,j=0;
99+
i = DAHDI_IOMUX_SIGEVENT;
100+
if (ioctl(fd, DAHDI_IOMUX, &i) == -1) return -1;
101+
if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) return -1;
102+
return j;
103+
}
104+
105+
static int set_hook(struct ast_channel *chan, int event)
106+
{
107+
int res = -1;
108+
struct dahdi_params dahdip;
109+
110+
memset(&dahdip, 0, sizeof(dahdip));
111+
res = ioctl(ast_channel_fd(chan, 0), DAHDI_GET_PARAMS, &dahdip);
112+
if (!res) {
113+
if (dahdip.sigtype & __DAHDI_SIG_FXS) {
114+
res = ioctl(ast_channel_fd(chan, 0), DAHDI_HOOK, &event);
115+
if (!res || (errno == EINPROGRESS)) {
116+
if (res) {
117+
/* Wait for the event to finish */
118+
dahdi_wait_event(ast_channel_fd(chan, 0));
119+
}
120+
ast_verb(5, "Went %s-hook on %s\n", event == DAHDI_ONHOOK ? "on" : "off", ast_channel_name(chan));
121+
} else {
122+
ast_log(LOG_WARNING, "Unable to go %s-hook on %s: %s\n", event == DAHDI_ONHOOK ? "on" : "off", ast_channel_name(chan), strerror(errno));
123+
}
124+
} else {
125+
ast_log(LOG_WARNING, "%s is not an FXO Channel\n", ast_channel_name(chan));
126+
}
127+
} else {
128+
ast_log(LOG_WARNING, "Unable to get parameters of %s: %s\n", ast_channel_name(chan), strerror(errno));
129+
}
130+
131+
return res;
132+
}
133+
134+
static int onhook_exec(struct ast_channel *chan, const char *data)
135+
{
136+
if (strcasecmp(ast_channel_tech(chan)->type, "DAHDI")) {
137+
ast_log(LOG_WARNING, "%s is not a DAHDI channel\n", ast_channel_name(chan));
138+
return -1;
139+
}
140+
return set_hook(chan, DAHDI_ONHOOK);
141+
}
142+
143+
static int offhook_exec(struct ast_channel *chan, const char *data)
144+
{
145+
if (strcasecmp(ast_channel_tech(chan)->type, "DAHDI")) {
146+
ast_log(LOG_WARNING, "%s is not a DAHDI channel\n", ast_channel_name(chan));
147+
return -1;
148+
}
149+
return set_hook(chan, DAHDI_OFFHOOK);
150+
}
151+
152+
static int supetest_exec(struct ast_channel *chan, const char *data)
153+
{
154+
if (strcasecmp(ast_channel_tech(chan)->type, "DAHDI")) {
155+
ast_log(LOG_WARNING, "%s is not a DAHDI channel\n", ast_channel_name(chan));
156+
return -1;
157+
}
158+
159+
#define CHECK_RES(x) if ((x)) { return -1; }
160+
161+
#define SUPE_SWAP_SINGLE(chan, onhook, offhook) \
162+
CHECK_RES(set_hook(chan, DAHDI_ONHOOK)); \
163+
CHECK_RES(ast_safe_sleep(chan, onhook)); \
164+
CHECK_RES(set_hook(chan, DAHDI_OFFHOOK)); \
165+
CHECK_RES(ast_safe_sleep(chan, offhook)); \
166+
167+
CHECK_RES(ast_raw_answer(chan)); /* First, go off hook */
168+
CHECK_RES(ast_safe_sleep(chan, 1000)); /* Pause a second before starting */
169+
170+
SUPE_SWAP_SINGLE(chan, 50, 1000); /* Momentary quick supervision blip, then pause a second */
171+
172+
/* Three supervision blips */
173+
SUPE_SWAP_SINGLE(chan, 170, 270);
174+
SUPE_SWAP_SINGLE(chan, 170, 270);
175+
SUPE_SWAP_SINGLE(chan, 170, 270);
176+
177+
CHECK_RES(ast_safe_sleep(chan, 1000)); /* Pause a second */
178+
179+
/* Momentary on-hooks, indefinitely. These blips are longer than the three before */
180+
for (;;) {
181+
SUPE_SWAP_SINGLE(chan, 200, 300);
182+
}
183+
return -1;
184+
}
185+
186+
static int unload_module(void)
187+
{
188+
ast_unregister_application(app_onhook);
189+
ast_unregister_application(app_offhook);
190+
ast_unregister_application(app_supetest);
191+
return 0;
192+
}
193+
194+
static int load_module(void)
195+
{
196+
int res = 0;
197+
res |= ast_register_application_xml(app_onhook, onhook_exec);
198+
res |= ast_register_application_xml(app_offhook, offhook_exec);
199+
res |= ast_register_application_xml(app_supetest, supetest_exec);
200+
return res;
201+
}
202+
203+
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel supervision application");

phreaknet.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2454,6 +2454,7 @@ phreak_patches() {
24542454
phreak_tree_module "apps/app_dialtone.c"
24552455
phreak_tree_module "apps/app_frame.c"
24562456
phreak_tree_module "apps/app_george.c"
2457+
phreak_tree_module "apps/app_hookstate.c"
24572458
phreak_tree_module "apps/app_keyprefetch.c"
24582459
phreak_tree_module "apps/app_loopplayback.c"
24592460
phreak_tree_module "apps/app_mail.c"

0 commit comments

Comments
 (0)