<p>N A has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/19749">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">chan_dahdi: Add on-hook ADSI script download support.<br><br>GetCPEID alludes to storing the CPEID for on-hook ADSI<br>script downloads, except there has never been any code to do this.<br><br>This adds code to save the CPE, as well as makes it possible<br>to initiate automatic feature downloads to idle (on-hook) CPE<br>on DAHDI FXS channels. As part of this change, GetCPEID now<br>saves CPEID for DAHDI channels, and ADSIProg now supports an<br>option that permits automatic feature downloads for on-hook CPE.<br>An AMI action and CLI command are added that allow an administrator<br>to spawn downloads to CPE on DAHDI channels.<br><br>ASTERISK-30374 #close<br><br>Change-Id: I3ca4d0037291ee824eceb88c58e07884bbbd8575<br>---<br>M apps/app_adsiprog.c<br>M apps/app_getcpeid.c<br>M channels/chan_dahdi.c<br>M channels/sig_analog.c<br>M channels/sig_analog.h<br>A doc/CHANGES-staging/adsionhook.txt<br>M include/asterisk/callerid.h<br>M main/callerid.c<br>8 files changed, 465 insertions(+), 17 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/49/19749/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/apps/app_adsiprog.c b/apps/app_adsiprog.c</span><br><span>index 26fe16b..7781d27 100644</span><br><span>--- a/apps/app_adsiprog.c</span><br><span>+++ b/apps/app_adsiprog.c</span><br><span>@@ -52,24 +52,53 @@</span><br><span> #include "asterisk/adsi.h"</span><br><span> #include "asterisk/utils.h"</span><br><span> #include "asterisk/lock.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/app.h"</span><br><span> </span><br><span> static const char app[] = "ADSIProg";</span><br><span> </span><br><span> /*** DOCUMENTATION</span><br><span> <application name="ADSIProg" language="en_US"></span><br><span> <synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- Load Asterisk ADSI Scripts into phone</span><br><span style="color: hsl(120, 100%, 40%);">+ Loads an ADSI script into a Type III (ADSI-capable) CPE.</span><br><span> </synopsis></span><br><span> <syntax></span><br><span> <parameter name="script" required="false"></span><br><span style="color: hsl(0, 100%, 40%);">- <para>adsi script to use. If not given uses the default script <filename>asterisk.adsi</filename></para></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>ADSI script to use. If not given uses the default script <filename>asterisk.adsi</filename></para></span><br><span style="color: hsl(120, 100%, 40%);">+ </parameter></span><br><span style="color: hsl(120, 100%, 40%);">+ <parameter name="options" required="false"></span><br><span style="color: hsl(120, 100%, 40%);">+ <optionlist></span><br><span style="color: hsl(120, 100%, 40%);">+ <option name="a"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>Automatic script upload (on-hook programming capability).</para></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>To use this capability, you should use the <literal>DAHDIAutoADSIProg</literal></span><br><span style="color: hsl(120, 100%, 40%);">+ AMI action or the <literal>dahdi send adsiprog</literal> CLI command to queue an</span><br><span style="color: hsl(120, 100%, 40%);">+ ADSI script for an automatic download to your CPE when it is idle.</span><br><span style="color: hsl(120, 100%, 40%);">+ The <literal>adsi</literal> extension in your CPE's incoming context should call</span><br><span style="color: hsl(120, 100%, 40%);">+ ADSIProg with the a option in order to transact the automatic script upload.</span><br><span style="color: hsl(120, 100%, 40%);">+ Your CPE will download the program and then go back on-hook automatically</span><br><span style="color: hsl(120, 100%, 40%);">+ once this has completed. No user intervention is required.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ <note><para>This is ONLY compatible with <literal>chan_dahdi</literal>.</para></note></span><br><span style="color: hsl(120, 100%, 40%);">+ </option></span><br><span style="color: hsl(120, 100%, 40%);">+ </optionlist></span><br><span> </parameter></span><br><span> </syntax></span><br><span> <description></span><br><span style="color: hsl(0, 100%, 40%);">- <para>This application programs an ADSI Phone with the given script</para></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>This application programs an ADSI Phone with the given script.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>This application can be used for off-hook programming of ADSI phones as well</span><br><span style="color: hsl(120, 100%, 40%);">+ as automatic feature downloads to idle (on-hook) CPE.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ <variablelist></span><br><span style="color: hsl(120, 100%, 40%);">+ <variable name="ADSIPROGSTATUS"></span><br><span style="color: hsl(120, 100%, 40%);">+ <value name="FAILURE"></span><br><span style="color: hsl(120, 100%, 40%);">+ Failed to upload the ADSI script</span><br><span style="color: hsl(120, 100%, 40%);">+ </value></span><br><span style="color: hsl(120, 100%, 40%);">+ <value name="SUCCESS"></span><br><span style="color: hsl(120, 100%, 40%);">+ Successfully uploaded the ADSI script</span><br><span style="color: hsl(120, 100%, 40%);">+ </value></span><br><span style="color: hsl(120, 100%, 40%);">+ </variable></span><br><span style="color: hsl(120, 100%, 40%);">+ </variablelist></span><br><span> </description></span><br><span> <see-also></span><br><span> <ref type="application">GetCPEID</ref></span><br><span style="color: hsl(120, 100%, 40%);">+ <ref type="manager">DAHDIAutoADSIProg</ref></span><br><span> <ref type="filename">adsi.conf</ref></span><br><span> </see-also></span><br><span> </application></span><br><span>@@ -1459,7 +1488,8 @@</span><br><span> }</span><br><span> #endif</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int adsi_prog(struct ast_channel *chan, const char *script)</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \param automatic 0 for off-hook downloads, 1 for automatic feature downloads */</span><br><span style="color: hsl(120, 100%, 40%);">+static int adsi_prog(struct ast_channel *chan, const char *script, int automatic)</span><br><span> {</span><br><span> struct adsi_script *scr;</span><br><span> int x, bytes;</span><br><span>@@ -1468,9 +1498,13 @@</span><br><span> if (!(scr = compile_script(script)))</span><br><span> return -1;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /* Start an empty ADSI Session */</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_adsi_load_session(chan, NULL, 0, 1) < 1)</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* If this is an automatic feature download, begin the download straight away (SR-3034, 3.3). */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!automatic) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Start an empty ADSI Session */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_adsi_load_session(chan, NULL, 0, 1) < 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> </span><br><span> /* Now begin the download attempt */</span><br><span> if (ast_adsi_begin_download(chan, scr->desc, scr->fdn, scr->sec, scr->ver)) {</span><br><span>@@ -1566,24 +1600,43 @@</span><br><span> return -1;</span><br><span> }</span><br><span> ast_free(scr);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_adsi_unload_session(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!automatic) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_adsi_unload_session(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span> static int adsi_exec(struct ast_channel *chan, const char *data)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- int res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *parse;</span><br><span style="color: hsl(120, 100%, 40%);">+ int automatic = 0, res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_DECLARE_APP_ARGS(args,</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_APP_ARG(script);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_APP_ARG(options);</span><br><span style="color: hsl(120, 100%, 40%);">+ );</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_strlen_zero(data))</span><br><span style="color: hsl(0, 100%, 40%);">- data = "asterisk.adsi";</span><br><span style="color: hsl(120, 100%, 40%);">+ parse = ast_strdupa(S_OR(data, ""));</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_STANDARD_APP_ARGS(args, parse);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(args.script)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ args.script = "asterisk.adsi";</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ast_strlen_zero(args.options)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ automatic = strchr(args.options, 'a') ? 1 : 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (automatic && strcasecmp(ast_channel_tech(chan)->type, "DAHDI")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "Automatic downloads only possible with DAHDI channels. Aborting!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> </span><br><span> if (!ast_adsi_available(chan)) {</span><br><span> ast_verb(3, "ADSI Unavailable on CPE. Not bothering to try.\n");</span><br><span> } else {</span><br><span> ast_verb(3, "ADSI Available on CPE. Attempting Upload.\n");</span><br><span style="color: hsl(0, 100%, 40%);">- res = adsi_prog(chan, data);</span><br><span style="color: hsl(120, 100%, 40%);">+ res = adsi_prog(chan, args.script, automatic);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ pbx_builtin_setvar_helper(chan, "ADSIPROGSTATUS", res ? "FAILURE" : "SUCCESS");</span><br><span> return res;</span><br><span> }</span><br><span> </span><br><span>diff --git a/apps/app_getcpeid.c b/apps/app_getcpeid.c</span><br><span>index abd9a82..4d4081a 100644</span><br><span>--- a/apps/app_getcpeid.c</span><br><span>+++ b/apps/app_getcpeid.c</span><br><span>@@ -32,6 +32,13 @@</span><br><span> </span><br><span> #include "asterisk.h"</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef HAVE_DAHDI</span><br><span style="color: hsl(120, 100%, 40%);">+#include <dahdi/user.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/frame.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "../channels/sig_analog.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "../channels/chan_dahdi.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #include "asterisk/lock.h"</span><br><span> #include "asterisk/file.h"</span><br><span> #include "asterisk/channel.h"</span><br><span>@@ -47,10 +54,27 @@</span><br><span> <syntax /></span><br><span> <description></span><br><span> <para>Obtains and displays ADSI CPE ID and other information in order</span><br><span style="color: hsl(0, 100%, 40%);">- to properly setup <filename>dahdi.conf</filename> for on-hook operations.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ to properly setup <literal>chan_dahdi</literal> for on-hook operations.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>If this application is called on a DAHDI FXS channel (FXO signalled),</span><br><span style="color: hsl(120, 100%, 40%);">+ then the CPEID received will be stored on the channel for future automatic</span><br><span style="color: hsl(120, 100%, 40%);">+ feature downloads to the CPE. When a CPE accepts an automatic download,</span><br><span style="color: hsl(120, 100%, 40%);">+ it will execute the <literal>adsi</literal> extension in the DAHDI channel's</span><br><span style="color: hsl(120, 100%, 40%);">+ configured context, which should be as follows:</span><br><span style="color: hsl(120, 100%, 40%);">+ <literal>exten => adsi,1,ADSIProg(${ADSIAUTOSCRIPT},a)</literal></para></span><br><span style="color: hsl(120, 100%, 40%);">+ <variablelist></span><br><span style="color: hsl(120, 100%, 40%);">+ <variable name="CPEID"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>The CPE ID if successfully received.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ </variable></span><br><span style="color: hsl(120, 100%, 40%);">+ </variablelist></span><br><span> </description></span><br><span style="color: hsl(120, 100%, 40%);">+ <see-also></span><br><span style="color: hsl(120, 100%, 40%);">+ <ref type="application">ADSIProg</ref></span><br><span style="color: hsl(120, 100%, 40%);">+ <ref type="manager">DAHDIAutoADSIProg</ref></span><br><span style="color: hsl(120, 100%, 40%);">+ <ref type="filename">adsi.conf</ref></span><br><span style="color: hsl(120, 100%, 40%);">+ </see-also></span><br><span> </application></span><br><span> ***/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static char *app = "GetCPEID";</span><br><span> </span><br><span> static int cpeid_setstatus(struct ast_channel *chan, char *stuff[], int voice)</span><br><span>@@ -100,11 +124,37 @@</span><br><span> }</span><br><span> }</span><br><span> if (res > -1) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (gotcpeid)</span><br><span style="color: hsl(0, 100%, 40%);">- snprintf(data[1], 80, "CPEID: %02hhx:%02hhx:%02hhx:%02hhx",</span><br><span style="color: hsl(0, 100%, 40%);">- cpeid[0], cpeid[1], cpeid[2], cpeid[3]);</span><br><span style="color: hsl(0, 100%, 40%);">- else</span><br><span style="color: hsl(120, 100%, 40%);">+ if (gotcpeid) {</span><br><span style="color: hsl(120, 100%, 40%);">+ char cpeidstr[12]; /* XX:XX:XX:XX */</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(cpeidstr, sizeof(cpeidstr), "%02hhx:%02hhx:%02hhx:%02hhx", cpeid[0], cpeid[1], cpeid[2], cpeid[3]);</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(data[1], 80, "CPEID: %s", cpeidstr);</span><br><span style="color: hsl(120, 100%, 40%);">+ pbx_builtin_setvar_helper(chan, "CPEID", cpeidstr);</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef HAVE_DAHDI</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!strcasecmp(ast_channel_tech(chan)->type, "DAHDI")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct dahdi_pvt *pvt;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct analog_pvt *analog_p;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct dahdi_params dahdip;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(&dahdip, 0, sizeof(dahdip));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ioctl(ast_channel_fd(chan, 0), DAHDI_GET_PARAMS, &dahdip)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "Unable to get parameters of %s: %s\n", ast_channel_name(chan), strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (dahdip.sigtype & __DAHDI_SIG_FXO) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* If we're a DAHDI channel, save the CPE ID for on-hook programming use. */</span><br><span style="color: hsl(120, 100%, 40%);">+ pvt = ast_channel_tech_pvt(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (pvt->adsi) {</span><br><span style="color: hsl(120, 100%, 40%);">+ analog_p = pvt->sig_pvt;</span><br><span style="color: hsl(120, 100%, 40%);">+ memcpy(analog_p->cpeid, cpeid, sizeof(analog_p->cpeid));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(1, "Saved CPE ID for DAHDI channel %d: '%02hhx:%02hhx:%02hhx:%02hhx'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ pvt->channel, cpeid[0], cpeid[1], cpeid[2], cpeid[3]);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span> strcpy(data[1], "CPEID Unknown");</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> if (gotgeometry)</span><br><span> snprintf(data[2], 80, "Geom: %dx%d, %d buttons", width, height, buttons);</span><br><span> else</span><br><span>diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c</span><br><span>index 5607eb0..7f7886b 100644</span><br><span>--- a/channels/chan_dahdi.c</span><br><span>+++ b/channels/chan_dahdi.c</span><br><span>@@ -393,6 +393,48 @@</span><br><span> <note><para>Feature only supported by analog channels.</para></note></span><br><span> </description></span><br><span> </manager></span><br><span style="color: hsl(120, 100%, 40%);">+ <manager name="DAHDIAutoADSIProg" language="en_US"></span><br><span style="color: hsl(120, 100%, 40%);">+ <synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+ Initiate an automatic ADSI feature download to an idle (on-hook) CPE</span><br><span style="color: hsl(120, 100%, 40%);">+ </synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+ <syntax></span><br><span style="color: hsl(120, 100%, 40%);">+ <parameter name="DAHDIChannel" required="true"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>DAHDI channel number on which to initiate download.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>You must have a Type III (ADSI-capable) CPE connected on this channel.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ </parameter></span><br><span style="color: hsl(120, 100%, 40%);">+ <parameter name="Script" required="false"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>ADSI script to download.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>The default, if not specified, is <literal>asterisk.adsi</literal>.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ </parameter></span><br><span style="color: hsl(120, 100%, 40%);">+ <parameter name="CPEID" required="false"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>The CPEID to use for the on-hook download attempt.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>If not specified, the last CPEID retrieved from the GetCPEID() application</span><br><span style="color: hsl(120, 100%, 40%);">+ will be used.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>If GetCPEID() has not been called on this channel while Asterisk is running,</span><br><span style="color: hsl(120, 100%, 40%);">+ this argument must be provided or the action will fail. The CPEID must match the</span><br><span style="color: hsl(120, 100%, 40%);">+ CPEID of a CPE on the channel or programming will fail.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ </parameter></span><br><span style="color: hsl(120, 100%, 40%);">+ </syntax></span><br><span style="color: hsl(120, 100%, 40%);">+ <description></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>Equivalent to the CLI command "dahdi send adsiprog <variable>channel</variable> <variable>script</variable> <variable>CPEID</variable>".</para></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>If this action is successful, that does not necessarily mean the feature download was successful. It only means that Asterisk will</span><br><span style="color: hsl(120, 100%, 40%);">+ attempt to begin the download. When the CPE accepts the download, it will go off-hook and execute the <literal>adsi</literal> extension</span><br><span style="color: hsl(120, 100%, 40%);">+ in the dialplan (in the phone's incoming context). You should call <literal>exten => adsi,1,ADSIProg(${ADSIAUTOSCRIPT},a)</literal></span><br><span style="color: hsl(120, 100%, 40%);">+ to actually send the script to the CPE. The CPE will automatically go back on-hook once the download has completed.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>The CPEID of the CPE must be known in advance in order to use this capability.</span><br><span style="color: hsl(120, 100%, 40%);">+ This can be done by calling GetCPEID() in the dialplan, or by manually providing</span><br><span style="color: hsl(120, 100%, 40%);">+ the CPEID to this action in the appropriate parameter.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>Asterisk will only attempt to initiate an automatic feature download if the channel has been idle for at least 45 seconds.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>Additionally, automatic feature downloads are only supported for scripts that CPE have previously requested during an off-hook session.</span><br><span style="color: hsl(120, 100%, 40%);">+ Attempts to upload completely new scripts that have not been previously seen by the phone will be rejected by the CPE.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>CPE may need to go off-hook between the initial download of a script and a future attempt to automatically update it.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ <note><para>Feature only supported by analog channels.</para></note></span><br><span style="color: hsl(120, 100%, 40%);">+ </description></span><br><span style="color: hsl(120, 100%, 40%);">+ <see-also></span><br><span style="color: hsl(120, 100%, 40%);">+ <ref type="application">ADSIProg</ref></span><br><span style="color: hsl(120, 100%, 40%);">+ <ref type="application">GetCPEID</ref></span><br><span style="color: hsl(120, 100%, 40%);">+ </see-also></span><br><span style="color: hsl(120, 100%, 40%);">+ </manager></span><br><span> <manager name="DAHDIShowChannels" language="en_US"></span><br><span> <synopsis></span><br><span> Show status of DAHDI channels.</span><br><span>@@ -2766,6 +2808,110 @@</span><br><span> return pvt;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define adsi_err(fd, s, m, ...) \</span><br><span style="color: hsl(120, 100%, 40%);">+ if (s && m) astman_send_error(s, m, "Failed to queue ADSI on-hook program"); \</span><br><span style="color: hsl(120, 100%, 40%);">+ else ast_cli(fd, __VA_ARGS__);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int adsi_onhook_init(struct dahdi_pvt *p, const char *cpeid, const char *script, int fd, struct mansession *s, const struct message *m)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int x;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned char cpeid_bytes[4];</span><br><span style="color: hsl(120, 100%, 40%);">+ struct analog_pvt *analog_p = p->sig_pvt;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Only FXS ports, please. */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (p->sig != SIG_FXOLS && p->sig != SIG_FXOGS && p->sig != SIG_FXOKS) {</span><br><span style="color: hsl(120, 100%, 40%);">+ adsi_err(fd, s, m, "DAHDI channel %d is not an FXS channel\n", p->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(cpeid_bytes, 0, sizeof(cpeid_bytes));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* We must know the CPE's CPE ID, since the CPE will compare it for a match.</span><br><span style="color: hsl(120, 100%, 40%);">+ * If we don't already know it and the user didn't provide one, abort. */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(cpeid)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Try to look up the CPEID on the pivot, from a previous invocation of GetCPEID(). */</span><br><span style="color: hsl(120, 100%, 40%);">+ memcpy(cpeid_bytes, analog_p->cpeid, sizeof(cpeid_bytes));</span><br><span style="color: hsl(120, 100%, 40%);">+ /* If we don't have a CPEID, we must abort, because without it, the on-hook alerting will fail. */</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(1, "Cached CPEID for channel %d: '%02hhx:%02hhx:%02hhx:%02hhx'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ p->channel, cpeid_bytes[0], cpeid_bytes[1], cpeid_bytes[2], cpeid_bytes[3]);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cpeid_bytes[0] == 0x00) {</span><br><span style="color: hsl(120, 100%, 40%);">+ adsi_err(fd, s, m, "No CPEID provided and none found in cache for DAHDI channel %d\n", p->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* We are expecting a string like 20:06:cc:c3 (this is what GetCPEID() outputs to the CLI)</span><br><span style="color: hsl(120, 100%, 40%);">+ * Need to convert it back into bytes. */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (sscanf(cpeid, "%02hhx:%02hhx:%02hhx:%02hhx", &cpeid_bytes[0], &cpeid_bytes[1], &cpeid_bytes[2], &cpeid_bytes[3]) != 4) {</span><br><span style="color: hsl(120, 100%, 40%);">+ adsi_err(fd, s, m, "Invalid CPE ID: %s\n", cpeid);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(1, "Using CPEID '%02hhx:%02hhx:%02hhx:%02hhx'\n", cpeid_bytes[0], cpeid_bytes[1], cpeid_bytes[2], cpeid_bytes[3]);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Only allow on-hook downloads on a quiescent FXS port. */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (analog_p->fxsoffhookstate || p->owner || analog_p->subs[SUB_REAL].owner) {</span><br><span style="color: hsl(120, 100%, 40%);">+ adsi_err(fd, s, m, "DAHDI channel %d is not currently idle\n", p->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ while (time(NULL) < analog_p->onhooktime + 45) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* CPE seem to ignore any on-hook programming attempts if they were in use</span><br><span style="color: hsl(120, 100%, 40%);">+ * as recently as 45 seconds ago (probably because it's highly likely</span><br><span style="color: hsl(120, 100%, 40%);">+ * during this time the phone could transition to non-idle... but why</span><br><span style="color: hsl(120, 100%, 40%);">+ * can't it just rely on us to make the right call? Ugh.)</span><br><span style="color: hsl(120, 100%, 40%);">+ * So, we may as well bail now. */</span><br><span style="color: hsl(120, 100%, 40%);">+ adsi_err(fd, s, m, "DAHDI channel %d was in use too recently (%d s ago)\n", p->channel, time(NULL) - analog_p->onhooktime);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (p->cidspill) {</span><br><span style="color: hsl(120, 100%, 40%);">+ adsi_err(fd, s, m, "CID spill already active on DAHDI channel %d\n", p->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Okay, we should be able to actually send the spill. */</span><br><span style="color: hsl(120, 100%, 40%);">+ p->mwisend_data.mwisend_current = MWI_SEND_SPILL;</span><br><span style="color: hsl(120, 100%, 40%);">+ p->mwisendactive = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ p->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!p->cidspill) {</span><br><span style="color: hsl(120, 100%, 40%);">+ p->mwisendactive = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ x = DAHDI_FLUSH_BOTH;</span><br><span style="color: hsl(120, 100%, 40%);">+ ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);</span><br><span style="color: hsl(120, 100%, 40%);">+ x = 3000;</span><br><span style="color: hsl(120, 100%, 40%);">+ ioctl(p->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* ADSI Automatic Feature Download (SR-2461 2.2.2.2)</span><br><span style="color: hsl(120, 100%, 40%);">+ * ADSI On-Hook Alerting (SR-2461 3.3.3.1, SR-3004 Sec 7, SR-3034 3.3, 2.5.5, 4.2.2)</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This is a completely unsolicited spill, not preceded by any ringing (so basically like MWI). */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Generate the FSK spill. */</span><br><span style="color: hsl(120, 100%, 40%);">+ p->cidlen = ast_callerid_adsi_alert_generate(p->cidspill, cpeid_bytes, AST_LAW(p));</span><br><span style="color: hsl(120, 100%, 40%);">+ p->cidpos = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* At this point, the spill has been queued, and mwi_send_process_buffer will actually</span><br><span style="color: hsl(120, 100%, 40%);">+ * do the work of ensuring the spill gets sent. Thank you very much!</span><br><span style="color: hsl(120, 100%, 40%);">+ * Yes, I know this isn't MWI, but it's a spill of the exact same type that needs to be sent,</span><br><span style="color: hsl(120, 100%, 40%);">+ * so we can let it do our work for us since it's just what we need. */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* The CPE will go off-hook once it gets the spill.</span><br><span style="color: hsl(120, 100%, 40%);">+ * At the point, we can simply call ADSIProg(), since that will send the CAS, receive the ACK, and continue.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Basically, our job here is just to get the phone to go off-hook on its own.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Then it can talk to the ADSI programming application, with the script to download as an argument</span><br><span style="color: hsl(120, 100%, 40%);">+ * Afterwards, it will hang up again on its own. */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* If the CPE goes off-hook within the next 2 seconds, consider this a positive response to the FSK spill.</span><br><span style="color: hsl(120, 100%, 40%);">+ * So, keep track of when we sent the spill. */</span><br><span style="color: hsl(120, 100%, 40%);">+ gettimeofday(&analog_p->adsionhooktime, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_copy_string(analog_p->adsionhookscript, S_OR(script, ""), sizeof(analog_p->adsionhookscript));</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int polarity_read(struct ast_channel *chan, const char *cmd, char *data, char *buffer, size_t buflen)</span><br><span> {</span><br><span> struct dahdi_pvt *pvt;</span><br><span>@@ -16377,6 +16523,50 @@</span><br><span> return CLI_SUCCESS;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static char *dahdi_send_adsionhookprog(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *script, *cpeid;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct dahdi_pvt *dahdi_chan = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case CLI_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+ e->command = "dahdi send adsiprog";</span><br><span style="color: hsl(120, 100%, 40%);">+ e->usage =</span><br><span style="color: hsl(120, 100%, 40%);">+ "Usage: dahdi send adsiprog <chan#> <script> [<cpeid>]\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " Initiates an automatic ADSI program download\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " to a CPE that is currently on-hook.\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " <chan num> is the channel number\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " <cpeid> CPEID override\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ ;</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ case CLI_GENERATE:</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (a->argc != 5 && a->argc != 6) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_SHOWUSAGE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ script = a->argv[4];</span><br><span style="color: hsl(120, 100%, 40%);">+ cpeid = a->argc == 6 ? a->argv[5] : NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ dahdi_chan = find_channel_from_str(a->argv[3]);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!dahdi_chan) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, "Unable to find given channel %s\n", a->argv[3]);</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_FAILURE;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (!dahdi_chan->adsi) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, "ADSI not enabled for channel %d\n", dahdi_chan->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_FAILURE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (adsi_onhook_init(dahdi_chan, cpeid, script, a->fd, NULL, NULL)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_FAILURE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, "ADSI Automatic Download initiated\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static struct ast_cli_entry dahdi_cli[] = {</span><br><span> AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),</span><br><span> AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),</span><br><span>@@ -16389,6 +16579,7 @@</span><br><span> AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),</span><br><span> AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),</span><br><span> AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_CLI_DEFINE(dahdi_send_adsionhookprog, "Initiate an automatic ADSI script download on a channel"),</span><br><span> };</span><br><span> </span><br><span> #define TRANSFER 0</span><br><span>@@ -16561,6 +16752,36 @@</span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int action_adsionhookprog(struct mansession *s, const struct message *m)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct dahdi_pvt *p;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *cpeid, *script, *channel;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ channel = astman_get_header(m, "DAHDIChannel");</span><br><span style="color: hsl(120, 100%, 40%);">+ cpeid = astman_get_header(m, "CPEID"); /* Potentially okay if NULL */</span><br><span style="color: hsl(120, 100%, 40%);">+ script = astman_get_header(m, "Script"); /* Potentially okay if NULL */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(channel)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ astman_send_error(s, m, "No channel specified");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ p = find_channel_from_str(channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!p) {</span><br><span style="color: hsl(120, 100%, 40%);">+ astman_send_error(s, m, "No such channel");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (!p->adsi) {</span><br><span style="color: hsl(120, 100%, 40%);">+ astman_send_error(s, m, "ADSI not enabled for channel %d", p->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (adsi_onhook_init(p, cpeid, script, -1, s, m)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ /* It won't happen immediately, just return success. */</span><br><span style="color: hsl(120, 100%, 40%);">+ astman_send_ack(s, m, "ADSI Automatic Download initiated");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int action_dahdishowchannels(struct mansession *s, const struct message *m)</span><br><span> {</span><br><span> struct dahdi_pvt *tmp = NULL;</span><br><span>@@ -17738,6 +17959,7 @@</span><br><span> ast_manager_unregister("DAHDITransfer");</span><br><span> ast_manager_unregister("DAHDIDNDoff");</span><br><span> ast_manager_unregister("DAHDIDNDon");</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_manager_unregister("DAHDIAutoADSIProg");</span><br><span> ast_manager_unregister("DAHDIShowChannels");</span><br><span> ast_manager_unregister("DAHDIRestart");</span><br><span> #if defined(HAVE_PRI)</span><br><span>@@ -19929,6 +20151,7 @@</span><br><span> ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);</span><br><span> ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);</span><br><span> ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_manager_register_xml("DAHDIAutoADSIProg", 0, action_adsionhookprog);</span><br><span> ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);</span><br><span> ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);</span><br><span> #if defined(HAVE_PRI)</span><br><span>diff --git a/channels/sig_analog.c b/channels/sig_analog.c</span><br><span>index b694a96..62dd116 100644</span><br><span>--- a/channels/sig_analog.c</span><br><span>+++ b/channels/sig_analog.c</span><br><span>@@ -2133,6 +2133,36 @@</span><br><span> case ANALOG_SIG_FXOLS:</span><br><span> case ANALOG_SIG_FXOGS:</span><br><span> case ANALOG_SIG_FXOKS:</span><br><span style="color: hsl(120, 100%, 40%);">+ if (p->subs[ANALOG_SUB_REAL].owner) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Check if this is CPE going off hook to download an incoming ADSI script.</span><br><span style="color: hsl(120, 100%, 40%);">+ * If the CPE went off-hook in response, then program it.</span><br><span style="color: hsl(120, 100%, 40%);">+ * (It doesn't matter whether immediate=yes or not).</span><br><span style="color: hsl(120, 100%, 40%);">+ * Note we don't have access to the DAHDI pivot, so we can't check p->adsi</span><br><span style="color: hsl(120, 100%, 40%);">+ * (that's on the DAHDI pivot, not the analog sig pivot)</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int ms_since_alert = ast_tvdiff_ms(ast_tvnow(), p->adsionhooktime);</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(&p->adsionhooktime, 0, sizeof(p->adsionhooktime)); /* Reset */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* CPE must go off-hook within 500 ms.</span><br><span style="color: hsl(120, 100%, 40%);">+ * However, there is a delay between when we queued the FSK spill,</span><br><span style="color: hsl(120, 100%, 40%);">+ * and it actually gets sent and received. So tack on an extra 2000ms for that. */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ms_since_alert < 2500) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_verb(3, "Automatic ADSI download of %s initiated on %s\n", p->adsionhookscript, ast_channel_name(p->subs[ANALOG_SUB_REAL].owner));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_setstate(chan, AST_STATE_UP);</span><br><span style="color: hsl(120, 100%, 40%);">+ analog_set_echocanceller(p, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* We just want to execute ADSIProg(p->adsionhookscript), really, but we have to start the PBX,</span><br><span style="color: hsl(120, 100%, 40%);">+ * so send the channel to the "adsi" extension and set ADSIAUTOSCRIPT so it knows what to do. */</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_channel_exten_set(p->subs[ANALOG_SUB_REAL].owner, "adsi");</span><br><span style="color: hsl(120, 100%, 40%);">+ pbx_builtin_setvar_helper(p->subs[ANALOG_SUB_REAL].owner, "ADSIAUTOSCRIPT", p->adsionhookscript);</span><br><span style="color: hsl(120, 100%, 40%);">+ res = ast_pbx_run(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (res) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "PBX exited non-zero\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ res = analog_play_tone(p, idx, ANALOG_TONE_CONGESTION);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ goto quit;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(1, "Elapsed time since ADSI on-hook spill is %u\n", ms_since_alert);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> /* Read the first digit */</span><br><span> timeout = analog_get_firstdigit_timeout(p);</span><br><span> /* If starting a threeway call, never timeout on the first digit so someone</span><br><span>diff --git a/channels/sig_analog.h b/channels/sig_analog.h</span><br><span>index 7e9acda..aa186d9 100644</span><br><span>--- a/channels/sig_analog.h</span><br><span>+++ b/channels/sig_analog.h</span><br><span>@@ -353,6 +353,11 @@</span><br><span> char *origcid_name; /*!< malloced original callerid */</span><br><span> char call_forward[AST_MAX_EXTENSION];</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* ADSI on-hook alerting */</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned char cpeid[4];</span><br><span style="color: hsl(120, 100%, 40%);">+ char adsionhookscript[64];</span><br><span style="color: hsl(120, 100%, 40%);">+ struct timeval adsionhooktime;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Ast channel to pass to __ss_analog_thread */</span><br><span> struct ast_channel *ss_astchan;</span><br><span> </span><br><span>diff --git a/doc/CHANGES-staging/adsionhook.txt b/doc/CHANGES-staging/adsionhook.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..82622d2</span><br><span>--- /dev/null</span><br><span>+++ b/doc/CHANGES-staging/adsionhook.txt</span><br><span>@@ -0,0 +1,4 @@</span><br><span style="color: hsl(120, 100%, 40%);">+Subject: chan_dahdi</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ADSI on-hook downloads (automatic feature downloads to</span><br><span style="color: hsl(120, 100%, 40%);">+idle ADSI CPE) are now supported.</span><br><span>diff --git a/include/asterisk/callerid.h b/include/asterisk/callerid.h</span><br><span>index 16a3df1..a85487e 100644</span><br><span>--- a/include/asterisk/callerid.h</span><br><span>+++ b/include/asterisk/callerid.h</span><br><span>@@ -236,6 +236,14 @@</span><br><span> int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, struct ast_format *codec, const char *name,</span><br><span> const char *number, int flags);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Generate an ADSI on-hook alerting signal for automatic feature download offer</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param buf</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param cpeid The CPEID of the CPE targeted for the download</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param codec</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_callerid_adsi_alert_generate(unsigned char *buf, unsigned char *cpeid, struct ast_format *codec);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! \brief Generate Caller-ID spill but in a format suitable for Call Waiting(tm)'s Caller*ID(tm)</span><br><span> * \see ast_callerid_generate() for other details</span><br><span> */</span><br><span>diff --git a/main/callerid.c b/main/callerid.c</span><br><span>index c6c29a0..4c970c8 100644</span><br><span>--- a/main/callerid.c</span><br><span>+++ b/main/callerid.c</span><br><span>@@ -938,6 +938,59 @@</span><br><span> return bytes;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+int ast_callerid_adsi_alert_generate(unsigned char *buf, unsigned char *cpeid, struct ast_format *codec)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char msg[256];</span><br><span style="color: hsl(120, 100%, 40%);">+ int len = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ int sum;</span><br><span style="color: hsl(120, 100%, 40%);">+ int x;</span><br><span style="color: hsl(120, 100%, 40%);">+ int bytes = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ float cr = 1.0;</span><br><span style="color: hsl(120, 100%, 40%);">+ float ci = 0.0;</span><br><span style="color: hsl(120, 100%, 40%);">+ float scont = 0.0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* MDMF */</span><br><span style="color: hsl(120, 100%, 40%);">+ msg[len++] = 0x80; /* SR-3363 3.3 */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Length is 6 */</span><br><span style="color: hsl(120, 100%, 40%);">+ msg[len++] = 6;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* "CPE ID Parameter" */</span><br><span style="color: hsl(120, 100%, 40%);">+ msg[len++] = 0xc;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Length of IE is 4 */</span><br><span style="color: hsl(120, 100%, 40%);">+ msg[len++] = 4;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* CPE ID: 4 bytes */</span><br><span style="color: hsl(120, 100%, 40%);">+ msg[len++] = cpeid[0];</span><br><span style="color: hsl(120, 100%, 40%);">+ msg[len++] = cpeid[1];</span><br><span style="color: hsl(120, 100%, 40%);">+ msg[len++] = cpeid[2];</span><br><span style="color: hsl(120, 100%, 40%);">+ msg[len++] = cpeid[3];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ sum = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ for (x = 0; x < len; x++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ sum += msg[x];</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ sum = (256 - (sum & 255));</span><br><span style="color: hsl(120, 100%, 40%);">+ msg[len++] = sum;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Wait a half a second */</span><br><span style="color: hsl(120, 100%, 40%);">+ for (x = 0; x < 4000; x++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ PUT_BYTE(0x7f);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Transmit 30 0x55's (looks like a square wave) for channel seizure */</span><br><span style="color: hsl(120, 100%, 40%);">+ for (x = 0; x < 30; x++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ PUT_CLID(0x55);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Send 170ms of callerid marks */</span><br><span style="color: hsl(120, 100%, 40%);">+ for (x = 0; x < 170; x++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ PUT_CLID_MARKMS;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ for (x = 0; x < len; x++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ PUT_CLID(msg[x]);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Send 50 more ms of marks */</span><br><span style="color: hsl(120, 100%, 40%);">+ for (x = 0; x < 50; x++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ PUT_CLID_MARKMS;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return bytes;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, struct ast_format *codec)</span><br><span> {</span><br><span> return callerid_full_generate(buf, number, name, NULL, -1, flags, CID_TYPE_MDMF, callwaiting, codec);</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/19749">change 19749</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/19749"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I3ca4d0037291ee824eceb88c58e07884bbbd8575 </div>
<div style="display:none"> Gerrit-Change-Number: 19749 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: N A <asterisk@phreaknet.org> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>