<p>Mark Murawski has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/19264">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">chan_dahdi: Add DAHDIBusyOut<br><br>This feature will 'busy out' a DAHDI channel in the traditional<br>PSTN/ISDN sense of making the line completely unavailable for<br>both incoming and outgoing calls.<br><br>If DAHDIBusyOut is turned on for a DAHDI channel, it will appear<br>for all intents and purposes that the channel is in use until<br>the DAHDIBusyOut is turned off for that channel.<br><br>The status of DAHDIBusyOut will not survive across Asterisk restarts.<br><br>Change-Id: Ib75c87c554bb18b8f65be73b4474474e7e1877b7<br>---<br>M channels/chan_dahdi.c<br>M channels/chan_dahdi.h<br>2 files changed, 546 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/64/19264/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c</span><br><span>index b829aa4..cb21a0c 100644</span><br><span>--- a/channels/chan_dahdi.c</span><br><span>+++ b/channels/chan_dahdi.c</span><br><span>@@ -129,6 +129,8 @@</span><br><span> #include "chan_dahdi.h"</span><br><span> #include "dahdi/bridge_native_dahdi.h"</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#include "regex.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*** DOCUMENTATION</span><br><span>      <application name="DAHDISendKeypadFacility" language="en_US"></span><br><span>              <synopsis></span><br><span>@@ -206,6 +208,24 @@</span><br><span>                      </example></span><br><span>             </description></span><br><span>         </function></span><br><span style="color: hsl(120, 100%, 40%);">+       <manager name="DAHDIBusyOut" language="en_US"></span><br><span style="color: hsl(120, 100%, 40%);">+               <synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                       Set BusyOut Mode on DAHDI Channel(s).</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%);">+                       <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" /></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(s) to change.  Comma delimited list of channels, with ability for ranges.  Example: 1,2,3  Example: 1-2,4-8</para></span><br><span style="color: hsl(120, 100%, 40%);">+                       </parameter></span><br><span style="color: hsl(120, 100%, 40%);">+                       <parameter name="Mode" required="true"></span><br><span style="color: hsl(120, 100%, 40%);">+                               <para>Boolean value, either enable or disable BusyOut</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>Enable or disable BusyOut on DAHDI channels.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                       <note><para>Valid only for analog channels.</para></note></span><br><span style="color: hsl(120, 100%, 40%);">+               </description></span><br><span style="color: hsl(120, 100%, 40%);">+       </manager></span><br><span>       <info name="CHANNEL" language="en_US" tech="DAHDI"></span><br><span>              <enumlist></span><br><span>                     <enum name="dahdi_channel"></span><br><span>@@ -1112,6 +1132,9 @@</span><br><span> static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);</span><br><span> static int dahdi_devicestate(const char *data);</span><br><span> static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);</span><br><span style="color: hsl(120, 100%, 40%);">+static int dahdi_set_channels_busyout(const char *channel_list, int on, int *touched_channels);</span><br><span style="color: hsl(120, 100%, 40%);">+static int dahdi_set_channel_busyout(struct dahdi_pvt *dahdi_chan, int on);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> </span><br><span> static struct ast_channel_tech dahdi_tech = {</span><br><span>      .type = "DAHDI",</span><br><span>@@ -5867,6 +5890,39 @@</span><br><span> #endif   /* defined(HAVE_PRI) */</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static char *dahdi_busyout_app = "DAHDIBusyOut";</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int dahdi_busyout_exec(struct ast_channel *chan, const char *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       char *params;</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(channel);</span><br><span style="color: hsl(120, 100%, 40%);">+               AST_APP_ARG(mode);</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 (ast_strlen_zero(data)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_log(LOG_WARNING, "DAHDIBusyOut requires two arguments!\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 style="color: hsl(120, 100%, 40%);">+       params = ast_strdupa(data);</span><br><span style="color: hsl(120, 100%, 40%);">+       AST_STANDARD_APP_ARGS(args, params);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!args.channel) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_log(LOG_WARNING, "DAHDIBusyOut requires a channel number!\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 style="color: hsl(120, 100%, 40%);">+       if (!args.mode) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_log(LOG_WARNING, "DAHDIBusyOut requires a mode!\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 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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #if defined(HAVE_PRI)</span><br><span> static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";</span><br><span> </span><br><span>@@ -8623,6 +8679,11 @@</span><br><span>     p->subs[idx].f.src = "dahdi_read";</span><br><span>      p->subs[idx].f.data.ptr = NULL;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+        if (p->busyout) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_mutex_unlock(&p->lock);</span><br><span style="color: hsl(120, 100%, 40%);">+               return &p->subs[idx].f;;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  /* make sure it sends initial key state as first frame */</span><br><span>    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))</span><br><span>  {</span><br><span>@@ -9719,6 +9780,22 @@</span><br><span> </span><br><span>       if (p->dsp)</span><br><span>               ast_dsp_digitreset(p->dsp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (p->busyout) {</span><br><span style="color: hsl(120, 100%, 40%);">+               struct ast_app *theapp;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               theapp = pbx_findapp("Answer");</span><br><span style="color: hsl(120, 100%, 40%);">+               res = pbx_exec(chan, theapp, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</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%);">+               }</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%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>    switch (p->sig) {</span><br><span>         case SIG_FEATD:</span><br><span>      case SIG_FEATDMF:</span><br><span>@@ -11743,6 +11820,10 @@</span><br><span>                                 break;</span><br><span>                       }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+                       if (i->busyout) {</span><br><span style="color: hsl(120, 100%, 40%);">+                               continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>                     if (thispass != lastpass) {</span><br><span>                          if (!found && ((i == last) || ((i == iflist) && !last))) {</span><br><span>                                   last = i;</span><br><span>@@ -11894,6 +11975,7 @@</span><br><span>                                  }</span><br><span>                                    res = dahdi_get_event(i->subs[SUB_REAL].dfd);</span><br><span>                                     ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>                                    /* Don't hold iflock while handling init events */</span><br><span>                                       ast_mutex_unlock(&iflock);</span><br><span>                                       if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {</span><br><span>@@ -15724,6 +15806,66 @@</span><br><span>    return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int action_dahdibusyout(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%);">+  const char *id = astman_get_header(m, "ActionID");</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *channel_arg = astman_get_header(m, "DAHDIChannel");</span><br><span style="color: hsl(120, 100%, 40%);">+     const char *mode_arg = astman_get_header(m, "Mode");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      char action_id[256] = "";</span><br><span style="color: hsl(120, 100%, 40%);">+   int touched_channels[DAHDI_MAX_SPANS];</span><br><span style="color: hsl(120, 100%, 40%);">+        int touched_channels_num = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ int on;</span><br><span style="color: hsl(120, 100%, 40%);">+       char *on_txt;</span><br><span style="color: hsl(120, 100%, 40%);">+ int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (ast_strlen_zero(channel_arg)) {</span><br><span style="color: hsl(120, 100%, 40%);">+           astman_send_error(s, m, "DAHDIBusyOut requires: DAHDIChannel");</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 (ast_strlen_zero(mode_arg)) {</span><br><span style="color: hsl(120, 100%, 40%);">+              astman_send_error(s, m, "DAHDIBusyOut requires: Mode");</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 (!ast_strlen_zero(id)) {</span><br><span style="color: hsl(120, 100%, 40%);">+           snprintf(action_id, sizeof(action_id), "ActionID: %s\r\n", id);</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%);">+   on = ast_true(mode_arg) ? 1 : 0;</span><br><span style="color: hsl(120, 100%, 40%);">+      on_txt = (on ? "On": "Off");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    astman_send_listack(s, m, "Dahdi BusyOut channels will follow", "start");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       dahdi_set_channels_busyout(channel_arg, on, touched_channels);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      for (i = 0; i < DAHDI_MAX_SPANS; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+           if (touched_channels[i] == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       continue;</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%);">+           /* touched_channels[channel] is going to be either -1 (failure), 0 (no change), 1 (set), or 2 (queued) */</span><br><span style="color: hsl(120, 100%, 40%);">+             astman_append(s,</span><br><span style="color: hsl(120, 100%, 40%);">+                      "Event: DahdiBusyOutChannel\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                    "Channel: %d\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                   "BusyOut: %s\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                   "%s"</span><br><span style="color: hsl(120, 100%, 40%);">+                "\r\n", i, (touched_channels[i] == 2 ? "Queued" : on_txt), action_id);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          touched_channels_num++;</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%);">+       astman_append(s,</span><br><span style="color: hsl(120, 100%, 40%);">+         "Event: DahdiBusyOutChannelListComplete\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+        "EventList: Complete\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "ListItems: %d\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "%s"</span><br><span style="color: hsl(120, 100%, 40%);">+        "\r\n", touched_channels_num, action_id);</span><br><span style="color: hsl(120, 100%, 40%);">+</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 char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)</span><br><span> {</span><br><span> #define FORMAT "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"</span><br><span>@@ -16372,6 +16514,55 @@</span><br><span>         return CLI_SUCCESS;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct dahdi_found_channel {</span><br><span style="color: hsl(120, 100%, 40%);">+       AST_LIST_ENTRY(dahdi_found_channel) entries;    /*!< Next group */</span><br><span style="color: hsl(120, 100%, 40%);">+       int channel_num;                                /*!< Index into dahdi iflist */</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_LIST_HEAD(dahdi_channel_list, dahdi_found_channel);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static char *dahdi_set_busy(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%);">+       int on;</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 set busyout";</span><br><span style="color: hsl(120, 100%, 40%);">+               e->usage =</span><br><span style="color: hsl(120, 100%, 40%);">+                       "Usage: dahdi set busyout <chan#> <on|off>\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                       "       Sets/resets Busyout mode on a channel.\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                       "       Changes take effect immediately.\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%);">+                       "       <chan num> can also be a comma delimited list of channels, ex 1,4,7\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                       "       <chan num> can also be a range of channels, ex 1-8\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                       "       <chan num> can also be a mix of channels and ranges, ex 1-2,4-8\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                       "       <chan num> can also be 'all'\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                       "       <on|off> Enable or disable Busyout mode?\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)</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%);">+       if (ast_true(a->argv[4]))</span><br><span style="color: hsl(120, 100%, 40%);">+               on = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+       else if (ast_false(a->argv[4]))</span><br><span style="color: hsl(120, 100%, 40%);">+               on = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       else {</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);</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%);">+        if (dahdi_set_channels_busyout(a->argv[3], on, NULL) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_cli(a->fd, "Unable to find channels matching: %s\n", a->argv[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%);">+       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>@@ -16384,6 +16575,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_set_busy, "Sets/resets Busyout mode on a channel"),</span><br><span> };</span><br><span> </span><br><span> #define TRANSFER 0</span><br><span>@@ -17705,6 +17897,7 @@</span><br><span>          }</span><br><span>    }</span><br><span>    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_unregister_application(dahdi_busyout_app);</span><br><span>         ast_unregister_application(dahdi_send_keypad_facility_app);</span><br><span> #ifdef HAVE_PRI_PROG_W_CAUSE</span><br><span>  ast_unregister_application(dahdi_send_callrerouting_facility_app);</span><br><span>@@ -17735,6 +17928,7 @@</span><br><span>         ast_manager_unregister("DAHDIDNDon");</span><br><span>      ast_manager_unregister("DAHDIShowChannels");</span><br><span>       ast_manager_unregister("DAHDIRestart");</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_manager_unregister("DAHDIBusyOut");</span><br><span> #if defined(HAVE_PRI)</span><br><span>         ast_manager_unregister("PRIShowSpans");</span><br><span>    ast_manager_unregister("PRIDebugSet");</span><br><span>@@ -19860,6 +20054,7 @@</span><br><span>   }</span><br><span>    pri_set_error(dahdi_pri_error);</span><br><span>      pri_set_message(dahdi_pri_message);</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_register_application_xml(dahdi_busyout_app, dahdi_busyout_exec);</span><br><span>     ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);</span><br><span> #ifdef HAVE_PRI_PROG_W_CAUSE</span><br><span>       ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);</span><br><span>@@ -19926,6 +20121,7 @@</span><br><span>       ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);</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 style="color: hsl(120, 100%, 40%);">+       ast_manager_register_xml("DAHDIBusyOut", 0, action_dahdibusyout);</span><br><span> #if defined(HAVE_PRI)</span><br><span>     ast_manager_register_xml("PRIShowSpans", 0, action_prishowspans);</span><br><span>  ast_manager_register_xml("PRIDebugSet", 0, action_pri_debug_set);</span><br><span>@@ -20058,6 +20254,322 @@</span><br><span>      return(0);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! \brief Do the actual busyout thread creation</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \note Lock dahdi_chan->lock before calling</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int dahdi_busyout_start(struct dahdi_pvt *dahdi_chan)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        int result;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_channel *chan;</span><br><span style="color: hsl(120, 100%, 40%);">+        pthread_t threadid;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        dahdi_chan->busyout_queued = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if ((chan = dahdi_new(dahdi_chan, AST_STATE_RING, 0, SUB_REAL, 0, NULL, NULL, NULL))) {</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_log(LOG_WARNING, "Could not create channel to handle call\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 style="color: hsl(120, 100%, 40%);">+        dahdi_chan->_busydetect = dahdi_chan->busydetect;</span><br><span style="color: hsl(120, 100%, 40%);">+        dahdi_chan->busydetect = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+        dahdi_chan->busyout    = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_devstate_changed(AST_STATE_BUSY, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/%d/busyout", dahdi_chan->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        result = _ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (result) {</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", dahdi_chan->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_hangup(chan);</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%);">+        ast_verb(1, "<DAHDI/%d> Enabled BusyOut\n", dahdi_chan->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+</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%);">+static void *dahdi_set_channel_busyout_on_thread(void *data);</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%);">+ * \brief Keep trying to set busyout on a channel that's currently in use</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%);">+static void *dahdi_set_channel_busyout_on_thread(void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct dahdi_pvt *dahdi_chan = data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       while (1) {</span><br><span style="color: hsl(120, 100%, 40%);">+               if (!dahdi_chan->busyout_queued) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       /* Busyout cancelled */</span><br><span style="color: hsl(120, 100%, 40%);">+                       ast_verb(1, "<DAHDI/%d> BusyOut try thread done\n", dahdi_chan->channel);</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 (dahdi_chan->busyout) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       /* Busyout already enabled */</span><br><span style="color: hsl(120, 100%, 40%);">+                       ast_verb(1, "<DAHDI/%d> BusyOut try thread done\n", dahdi_chan->channel);</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%);">+               ast_mutex_lock(&dahdi_chan->lock);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               if (!dahdi_chan->owner) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       /* Current call finished */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                       dahdi_busyout_start(dahdi_chan);</span><br><span style="color: hsl(120, 100%, 40%);">+                       ast_mutex_unlock(&dahdi_chan->lock);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                       ast_verb(1, "<DAHDI/%d> BusyOut try thread done\n", dahdi_chan->channel);</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%);">+               ast_mutex_unlock(&dahdi_chan->lock);</span><br><span style="color: hsl(120, 100%, 40%);">+               usleep(1000);</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%);">+       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%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Set busyout status on a list or range of channels</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param channel_list Comma delimited list of channels, may contain ranges</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param touched_channels pointer to integer array preallocated to the size of DAHDI_MAX_SPANS that holds the channels changed</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \detail</span><br><span style="color: hsl(120, 100%, 40%);">+ *   touched_channels[channel] is going to be either -1 (failure), 0 (no change), 1 (set), or 2 (queued)</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \example channel_list = "1"</span><br><span style="color: hsl(120, 100%, 40%);">+ * \example channel_list = "1,2"</span><br><span style="color: hsl(120, 100%, 40%);">+ * \example channel_list = "1,2-4"</span><br><span style="color: hsl(120, 100%, 40%);">+ * \example channel_list = "1-4,6-8"</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval >0 Count of channels that have had busyout status changed</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval 0 No channel busyout status has been changed</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int dahdi_set_channels_busyout(const char *channel_list, int on, int *touched_channels)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        int channel;</span><br><span style="color: hsl(120, 100%, 40%);">+  int channel_to;</span><br><span style="color: hsl(120, 100%, 40%);">+       int channels_touched = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     int fail_match;</span><br><span style="color: hsl(120, 100%, 40%);">+       int have_comma_remaining;</span><br><span style="color: hsl(120, 100%, 40%);">+     int i;</span><br><span style="color: hsl(120, 100%, 40%);">+        int match_comma_len;</span><br><span style="color: hsl(120, 100%, 40%);">+  int match_len;</span><br><span style="color: hsl(120, 100%, 40%);">+        int result;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ char *channel_arg;</span><br><span style="color: hsl(120, 100%, 40%);">+    char *channel_arg_cur;</span><br><span style="color: hsl(120, 100%, 40%);">+        const char *match_start;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct dahdi_pvt *dahdi_chan = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct ast_str *match_str = ast_str_create(64);</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ast_str *match_str_from = ast_str_create(64);</span><br><span style="color: hsl(120, 100%, 40%);">+  struct ast_str *match_str_to = ast_str_create(64);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  regex_t regexbuf_comma;</span><br><span style="color: hsl(120, 100%, 40%);">+       regex_t regexbuf_dash;</span><br><span style="color: hsl(120, 100%, 40%);">+        regmatch_t reg_m[DAHDI_MAX_SPANS];</span><br><span style="color: hsl(120, 100%, 40%);">+    int dahdi_channels_search[DAHDI_MAX_SPANS];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ channel_arg = ast_strdup(channel_list);</span><br><span style="color: hsl(120, 100%, 40%);">+       channel_arg_cur = channel_arg;</span><br><span style="color: hsl(120, 100%, 40%);">+        memset(&dahdi_channels_search, 0, sizeof(dahdi_channels_search));</span><br><span style="color: hsl(120, 100%, 40%);">+       memset(touched_channels, 0, (DAHDI_MAX_SPANS * sizeof(int)));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+//     ast_log(LOG_NOTICE, "channels: %s\n", channel_arg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (regcomp(&regexbuf_comma, "^([0-9-]+)(,|$)(.+)?", REG_EXTENDED)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            /* We should never fail */</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_log(LOG_ERROR, "Regex compile failed in dahdi_set_busy()\n");</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%);">+       if (regcomp(&regexbuf_dash, "^([0-9]+)-(.*)", REG_EXTENDED)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            /* We should never fail */</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_log(LOG_ERROR, "Regex compile failed in dahdi_set_busy()\n");</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%);">+  do {</span><br><span style="color: hsl(120, 100%, 40%);">+         fail_match = regexec(&regexbuf_comma, channel_arg_cur, 4, reg_m, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+              if (fail_match) {</span><br><span style="color: hsl(120, 100%, 40%);">+//                   ast_log(LOG_ERROR, "regex match fail (%d): %s\n", fail_match, channel_arg_cur);</span><br><span style="color: hsl(120, 100%, 40%);">+                     break;</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%);">+            match_start      = (channel_arg_cur + reg_m[1].rm_so);</span><br><span style="color: hsl(120, 100%, 40%);">+                match_comma_len  = (reg_m[1].rm_eo - reg_m[1].rm_so);</span><br><span style="color: hsl(120, 100%, 40%);">+         *(channel_arg_cur + match_comma_len) = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_str_set(&match_str, 0, "%s", match_start);</span><br><span style="color: hsl(120, 100%, 40%);">+//        ast_log(LOG_NOTICE, "regex match: [%d:%d] %s (%d)\n", reg_m[1].rm_so, reg_m[1].rm_eo, ast_str_buffer(match_str), match_comma_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         if (reg_m[3].rm_so != -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+//                ast_log(LOG_NOTICE, "Comma remaining at: %d\n", reg_m[2].rm_so);</span><br><span style="color: hsl(120, 100%, 40%);">+                    have_comma_remaining = 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%);">+                       have_comma_remaining = 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%);">+          fail_match = regexec(&regexbuf_dash, ast_str_buffer(match_str), 3, reg_m, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+             if (fail_match) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      channel = atoi(ast_str_buffer(match_str));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                  if (channel && (channel < DAHDI_MAX_SPANS)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                             dahdi_channels_search[channel] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+//                         ast_log(LOG_NOTICE, "num: %d\n", channel);</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%);">+              else {</span><br><span style="color: hsl(120, 100%, 40%);">+//                        ast_log(LOG_NOTICE, "process range: %s\n", ast_str_buffer(match_str));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                 match_start  = (ast_str_buffer(match_str) + reg_m[1].rm_so);</span><br><span style="color: hsl(120, 100%, 40%);">+                  match_len    = (reg_m[1].rm_eo - reg_m[1].rm_so);</span><br><span style="color: hsl(120, 100%, 40%);">+                     *(ast_str_buffer(match_str) + match_len) = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                 ast_str_set(&match_str_from, 0, "%s", match_start);</span><br><span style="color: hsl(120, 100%, 40%);">+//                      ast_log(LOG_NOTICE, "range regex match: [%d:%d] %s (%d)\n", reg_m[1].rm_so, reg_m[1].rm_eo, ast_str_buffer(match_str_from), match_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                match_start  = (ast_str_buffer(match_str) + reg_m[2].rm_so);</span><br><span style="color: hsl(120, 100%, 40%);">+                  match_len    = (reg_m[2].rm_eo - reg_m[2].rm_so);</span><br><span style="color: hsl(120, 100%, 40%);">+//                   *(ast_str_buffer(match_str) + match_len) = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                  ast_str_set(&match_str_to, 0, "%s", match_start);</span><br><span style="color: hsl(120, 100%, 40%);">+//                       ast_log(LOG_NOTICE, "range regex match: [%d:%d] %s (%d)\n", reg_m[2].rm_so, reg_m[2].rm_eo, ast_str_buffer(match_str_to), match_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                   channel    = atoi(ast_str_buffer(match_str_from));</span><br><span style="color: hsl(120, 100%, 40%);">+                    channel_to = atoi(ast_str_buffer(match_str_to));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+//                 ast_log(LOG_NOTICE, "range: %d->%d\n", channel, channel_to);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (channel && channel_to && (channel < DAHDI_MAX_SPANS) && (channel_to < DAHDI_MAX_SPANS)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                          for (i = channel; i <= channel_to; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                  dahdi_channels_search[i] = 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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            /* skip past the current match */</span><br><span style="color: hsl(120, 100%, 40%);">+             channel_arg_cur += match_comma_len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         /* skip past the comma between matches */</span><br><span style="color: hsl(120, 100%, 40%);">+             if (have_comma_remaining) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  channel_arg_cur++;</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 (*channel_arg_cur);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+//   for (i = 0; i < DAHDI_MAX_SPANS; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+//                  if (dahdi_channels_search[i]) {</span><br><span style="color: hsl(120, 100%, 40%);">+//                  ast_log(LOG_NOTICE, "select -> %d\n", i);</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_mutex_lock(&iflock);</span><br><span style="color: hsl(120, 100%, 40%);">+       for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+         channel = dahdi_chan->channel;</span><br><span style="color: hsl(120, 100%, 40%);">+             if ((channel < 0) || !dahdi_channels_search[channel]) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    continue;</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%);">+           /* Found the channel. Actually set it */</span><br><span style="color: hsl(120, 100%, 40%);">+               channels_touched++;</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_verb(1, "<DAHDI/%d> Setting BusyOut Mode to: %s\n", channel, (on ? "On" : "Off"));</span><br><span style="color: hsl(120, 100%, 40%);">+            result = dahdi_set_channel_busyout(dahdi_chan, on);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         if (touched_channels) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* -1 (failure), 0 (no change), 1 (set), or 2 (queued) */</span><br><span style="color: hsl(120, 100%, 40%);">+                     touched_channels[channel] = result;</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_mutex_unlock(&iflock);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      regfree(&regexbuf_comma);</span><br><span style="color: hsl(120, 100%, 40%);">+ regfree(&regexbuf_dash);</span><br><span style="color: hsl(120, 100%, 40%);">+  ast_free(channel_arg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      return channels_touched;</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%);">+ * \brief Set the BusyOut mode on a specific dahdi channel</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param on Value of 0 for Disable, 1 for Enable</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval 0 on no change</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval 1 on change</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval 2 on queue of operation</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval -1 on failure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int dahdi_set_channel_busyout(struct dahdi_pvt *dahdi_chan, int on)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       int result = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (on) {</span><br><span style="color: hsl(120, 100%, 40%);">+               if (dahdi_chan->busyout) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       ast_verb(1, "<DAHDI/%d> BusyOut already enabled\n", dahdi_chan->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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               if (dahdi_chan->owner) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       pthread_t busyout_trying_threadid;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                        if (dahdi_chan->busyout_queued) {</span><br><span style="color: hsl(120, 100%, 40%);">+                               ast_log(LOG_WARNING, "Channel DAHDI/%d already has a busyout queued\n", dahdi_chan->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%);">+                       ast_log(LOG_NOTICE, "Channel DAHDI/%d already has a call, queueing busyout\n", dahdi_chan->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+                       dahdi_chan->busyout_queued = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+                       result = ast_pthread_create_detached(&busyout_trying_threadid, NULL, dahdi_set_channel_busyout_on_thread, dahdi_chan);</span><br><span style="color: hsl(120, 100%, 40%);">+                       if (result) {</span><br><span style="color: hsl(120, 100%, 40%);">+                               ast_log(LOG_WARNING, "Unable to start busyout queue thread on channel DAHDI/%d\n", dahdi_chan->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%);">+                       return 2;</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_mutex_lock(&dahdi_chan->lock);</span><br><span style="color: hsl(120, 100%, 40%);">+               dahdi_busyout_start(dahdi_chan);</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_mutex_unlock(&dahdi_chan->lock);</span><br><span style="color: hsl(120, 100%, 40%);">+</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%);">+       /* off */</span><br><span style="color: hsl(120, 100%, 40%);">+        if (dahdi_chan->busyout_queued) {</span><br><span style="color: hsl(120, 100%, 40%);">+               dahdi_chan->busyout_queued = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_log(LOG_WARNING, "Channel DAHDI/%d busyout queue cancelled\n", dahdi_chan->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%);">+       if (!dahdi_chan->busyout) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_verb(1, "<DAHDI/%d> BusyOut already disabled\n", dahdi_chan->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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_mutex_lock(&dahdi_chan->lock);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       dahdi_chan->busyout_queued = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       dahdi_chan->busydetect = dahdi_chan->_busydetect;</span><br><span style="color: hsl(120, 100%, 40%);">+       dahdi_chan->busyout    = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/%d/busyout", dahdi_chan->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (dahdi_chan->owner) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_hangup(dahdi_chan->owner);</span><br><span style="color: hsl(120, 100%, 40%);">+               dahdi_set_hook(dahdi_chan->subs[SUB_REAL].dfd, DAHDI_ONHOOK);</span><br><span style="color: hsl(120, 100%, 40%);">+               dahdi_fake_event(dahdi_chan, HANGUP);</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%);">+        /* Clear pending Ring/Answered from our busyout call */</span><br><span style="color: hsl(120, 100%, 40%);">+        dahdi_get_event(dahdi_chan->subs[SUB_REAL].dfd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_mutex_unlock(&dahdi_chan->lock);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_verb(1, "<DAHDI/%d> Disabled BusyOut\n", dahdi_chan->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span> static int reload(void)</span><br><span> {</span><br><span>diff --git a/channels/chan_dahdi.h b/channels/chan_dahdi.h</span><br><span>index de813f2..13db791 100644</span><br><span>--- a/channels/chan_dahdi.h</span><br><span>+++ b/channels/chan_dahdi.h</span><br><span>@@ -203,6 +203,21 @@</span><br><span>        * \note Set from the "busydetect" value read in from chan_dahdi.conf</span><br><span>       */</span><br><span>  unsigned int busydetect:1;</span><br><span style="color: hsl(120, 100%, 40%);">+       /*!</span><br><span style="color: hsl(120, 100%, 40%);">+        * \brief TRUE if busyout mode is enabled as per configured (backup of busydetect setting for when in busyout mode).</span><br><span style="color: hsl(120, 100%, 40%);">+        * (Listens for the beep-beep busy pattern.)</span><br><span style="color: hsl(120, 100%, 40%);">+        * \note Set from the "busydetect" value read in from chan_dahdi.conf</span><br><span style="color: hsl(120, 100%, 40%);">+        */</span><br><span style="color: hsl(120, 100%, 40%);">+       unsigned int _busydetect:1;</span><br><span style="color: hsl(120, 100%, 40%);">+       /*!</span><br><span style="color: hsl(120, 100%, 40%);">+        * \brief TRUE if busyout mode is enabled.</span><br><span style="color: hsl(120, 100%, 40%);">+        */</span><br><span style="color: hsl(120, 100%, 40%);">+       unsigned int busyout:1;</span><br><span style="color: hsl(120, 100%, 40%);">+       /*!</span><br><span style="color: hsl(120, 100%, 40%);">+        * \brief TRUE if busyout mode is queued for enable.</span><br><span style="color: hsl(120, 100%, 40%);">+        * (If we have a call in progress, we will keep trying to enable busyout until the call is done)</span><br><span style="color: hsl(120, 100%, 40%);">+        */</span><br><span style="color: hsl(120, 100%, 40%);">+       unsigned int busyout_queued:1;</span><br><span>     /*!</span><br><span>   * \brief TRUE if call return is enabled.</span><br><span>     * (*69, if your dialplan doesn't catch this first)</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/19264">change 19264</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/+/19264"/><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: Ib75c87c554bb18b8f65be73b4474474e7e1877b7 </div>
<div style="display:none"> Gerrit-Change-Number: 19264 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Mark Murawski <markm@intellasoft.net> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>