]> git.pld-linux.org Git - packages/asterisk.git/commitdiff
- updated to todays version
authorArkadiusz Miśkiewicz <arekm@maven.pl>
Wed, 16 Jul 2008 19:04:57 +0000 (19:04 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    asterisk-bristuff.patch -> 1.7

asterisk-bristuff.patch

index acc71fad32ac3bf0eebef7b44e52dffc3c5ef500..12adbedd2b756f0046da1e39b351bf7c4f3aad53 100644 (file)
@@ -57,7 +57,7 @@
  
 --- a/main/asterisk.c
 +++ b/main/asterisk.c
-@@ -2387,6 +2387,7 @@ static void ast_readconfig(void) 
+@@ -2427,6 +2427,7 @@ static void ast_readconfig(void) 
        ast_copy_string(ast_config_AST_PID, AST_PID, sizeof(ast_config_AST_PID));
        ast_copy_string(ast_config_AST_SOCKET, AST_SOCKET, sizeof(ast_config_AST_SOCKET));
        ast_copy_string(ast_config_AST_RUN_DIR, AST_RUN_DIR, sizeof(ast_config_AST_RUN_DIR));
@@ -65,7 +65,7 @@
  
        /* no asterisk.conf? no problem, use buildtime config! */
        if (!cfg) {
-@@ -2511,6 +2512,8 @@ static void ast_readconfig(void) 
+@@ -2551,6 +2552,8 @@ static void ast_readconfig(void) 
                        ast_copy_string(ast_config_AST_RUN_GROUP, v->value, sizeof(ast_config_AST_RUN_GROUP));
                } else if (!strcasecmp(v->name, "systemname")) {
                        ast_copy_string(ast_config_AST_SYSTEM_NAME, v->value, sizeof(ast_config_AST_SYSTEM_NAME));
                }
 --- a/include/asterisk/agi.h
 +++ b/include/asterisk/agi.h
-@@ -29,7 +29,8 @@ extern "C" {
+@@ -30,6 +30,7 @@ extern "C" {
  typedef struct agi_state {
        int fd;         /* FD for general output */
--      int audio;      /* FD for audio output */
-+      int audio_out;  /* FD for audio output */
+       int audio;      /* FD for audio output */
 +      int audio_in;   /* FD for audio output */
        int ctrl;       /* FD for input control */
        unsigned int fast:1; /* flag for fast agi or not */
 +                      return AGI_RESULT_FAILURE;
 +              }
 +              res = fcntl(audio2[0], F_GETFL);
-+              if (res > -1) 
++              if (res > -1)
 +                      res = fcntl(audio2[0], F_SETFL, res | O_NONBLOCK);
 +              if (res < 0) {
 +                      ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno));
  
                /* Close everything but stdin/out/error */
 -              for (x=STDERR_FILENO + 2;x<1024;x++) 
-+              for (x=STDERR_FILENO + 3;x<1024;x++) 
++              for (x=STDERR_FILENO + 3;x<1024;x++)
                        close(x);
  
                /* Execute script */
-@@ -357,12 +398,19 @@ static enum agi_result launch_script(cha
+@@ -359,12 +400,19 @@ static enum agi_result launch_script(cha
        if (efd) {
                *efd = audio[1];
        }
  
        *opid = pid;
        return AGI_RESULT_SUCCESS;
-@@ -392,7 +440,7 @@ static void setup_env(struct ast_channel
+@@ -394,7 +442,7 @@ static void setup_env(struct ast_channel
        fdprintf(fd, "agi_context: %s\n", chan->context);
        fdprintf(fd, "agi_extension: %s\n", chan->exten);
        fdprintf(fd, "agi_priority: %d\n", chan->priority);
  
        /* User information */
        fdprintf(fd, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : "");
-@@ -421,7 +469,7 @@ static int handle_waitfordigit(struct as
-               return RESULT_SHOWUSAGE;
-       if (sscanf(argv[3], "%d", &to) != 1)
-               return RESULT_SHOWUSAGE;
--      res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl);
-+      res = ast_waitfordigit_full(chan, to, agi->audio_out, agi->ctrl);
-       fdprintf(agi->fd, "200 result=%d\n", res);
-       return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
- }
-@@ -596,7 +644,7 @@ static int handle_streamfile(struct ast_
-       if (vfs)
-               ast_playstream(vfs);
-       
--      res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
-+      res = ast_waitstream_full(chan, argv[3], agi->audio_out, agi->ctrl);
-       /* this is to check for if ast_waitstream closed the stream, we probably are at
-        * the end of the stream, return that amount, else check for the amount */
-       sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length;
-@@ -657,7 +705,7 @@ static int handle_getoption(struct ast_c
-       if (vfs)
-               ast_playstream(vfs);
--      res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
-+      res = ast_waitstream_full(chan, argv[3], agi->audio_out, agi->ctrl);
-       /* this is to check for if ast_waitstream closed the stream, we probably are at
-        * the end of the stream, return that amount, else check for the amount */
-       sample_offset = (chan->stream)?ast_tellstream(fs):max_length;
-@@ -669,7 +717,7 @@ static int handle_getoption(struct ast_c
-       /* If the user didnt press a key, wait for digitTimeout*/
-       if (res == 0 ) {
--              res = ast_waitfordigit_full(chan, timeout, agi->audio, agi->ctrl);
-+              res = ast_waitfordigit_full(chan, timeout, agi->audio_out, agi->ctrl);
-               /* Make sure the new result is in the escape digits of the GET OPTION */
-               if ( !strchr(edigits,res) )
-                       res=0;
-@@ -693,7 +741,7 @@ static int handle_saynumber(struct ast_c
-               return RESULT_SHOWUSAGE;
-       if (sscanf(argv[2], "%d", &num) != 1)
-               return RESULT_SHOWUSAGE;
--      res = ast_say_number_full(chan, num, argv[3], chan->language, (char *) NULL, agi->audio, agi->ctrl);
-+      res = ast_say_number_full(chan, num, argv[3], chan->language, (char *) NULL, agi->audio_out, agi->ctrl);
-       if (res == 1)
-               return RESULT_SUCCESS;
-       fdprintf(agi->fd, "200 result=%d\n", res);
-@@ -710,7 +758,7 @@ static int handle_saydigits(struct ast_c
-       if (sscanf(argv[2], "%d", &num) != 1)
-               return RESULT_SHOWUSAGE;
--      res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
-+      res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio_out, agi->ctrl);
-       if (res == 1) /* New command */
-               return RESULT_SUCCESS;
-       fdprintf(agi->fd, "200 result=%d\n", res);
-@@ -724,7 +772,7 @@ static int handle_sayalpha(struct ast_ch
-       if (argc != 4)
-               return RESULT_SHOWUSAGE;
--      res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
-+      res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio_out, agi->ctrl);
-       if (res == 1) /* New command */
-               return RESULT_SUCCESS;
-       fdprintf(agi->fd, "200 result=%d\n", res);
-@@ -802,7 +850,7 @@ static int handle_sayphonetic(struct ast
-       if (argc != 4)
-               return RESULT_SHOWUSAGE;
--      res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
-+      res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio_out, agi->ctrl);
-       if (res == 1) /* New command */
-               return RESULT_SUCCESS;
-       fdprintf(agi->fd, "200 result=%d\n", res);
-@@ -826,7 +874,7 @@ static int handle_getdata(struct ast_cha
-               max = atoi(argv[4]); 
-       else
-               max = 1024;
--      res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl);
-+      res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio_out, agi->ctrl);
-       if (res == 2)                   /* New command */
-               return RESULT_SUCCESS;
-       else if (res == 1)
-@@ -1833,8 +1881,13 @@ static enum agi_result run_agi(struct as
+@@ -1835,8 +1883,13 @@ static enum agi_result run_agi(struct as
        int ms;
        enum agi_result returnstatus = AGI_RESULT_SUCCESS;
        struct ast_frame *f;
        FILE *readf;
        /* how many times we'll retry if ast_waitfor_nandfs will return without either 
          channel or file descriptor in case select is interrupted by a system call (EINTR) */
-@@ -1848,10 +1901,22 @@ static enum agi_result run_agi(struct as
+@@ -1850,10 +1903,22 @@ static enum agi_result run_agi(struct as
                return AGI_RESULT_FAILURE;
        }
        setlinebuf(readf);
 -      setup_env(chan, request, agi->fd, (agi->audio > -1));
-+      if (agi->audio_out > -1) {
++      if (agi->audio > -1) {
 +          enhanced = 1;
 +      }
 +      if (agi->audio_in > -1) {
                if (c) {
                        retry = AGI_NANDFS_RETRY;
                        /* Idle the channel until we get a command */
-@@ -1862,13 +1927,23 @@ static enum agi_result run_agi(struct as
-                               break;
-                       } else {
-                               /* If it's voice, write it to the audio pipe */
--                              if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) {
-+                              if ((agi->audio_out > -1) && (f->frametype == AST_FRAME_VOICE)) {
-                                       /* Write, ignoring errors */
--                                      write(agi->audio, f->data, f->datalen);
-+                                      write(agi->audio_out, f->data, f->datalen);
-                               }
+@@ -1871,6 +1936,16 @@ static enum agi_result run_agi(struct as
                                ast_frfree(f);
                        }
                } else if (outfd > -1) {
                        size_t len = sizeof(buf);
                        size_t buflen = 0;
  
-@@ -1914,6 +1989,7 @@ static enum agi_result run_agi(struct as
+@@ -1922,6 +1997,7 @@ static enum agi_result run_agi(struct as
                        if ((returnstatus < 0) || (returnstatus == AST_PBX_KEEPALIVE)) {
                                break;
                        }
                } else {
                        if (--retry <= 0) {
                                ast_log(LOG_WARNING, "No channel, no fd?\n");
-@@ -2022,6 +2098,7 @@ static int agi_exec_full(struct ast_chan
+@@ -2030,6 +2106,7 @@ static int agi_exec_full(struct ast_chan
        int argc = 0;
        int fds[2];
        int efd = -1;
        int pid;
          char *stringp;
        AGI agi;
-@@ -2047,12 +2124,13 @@ static int agi_exec_full(struct ast_chan
-               }
+@@ -2056,12 +2133,13 @@ static int agi_exec_full(struct ast_chan
        }
  #endif
+       ast_replace_sigchld();
 -      res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, &pid);
 +      res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, (enhanced == 2) ? &efd2 : NULL, &pid);
        if (res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) {
                int status = 0;
                agi.fd = fds[1];
                agi.ctrl = fds[0];
--              agi.audio = efd;
-+              agi.audio_out = efd;
+               agi.audio = efd;
 +              agi.audio_in = efd2;
                agi.fast = (res == AGI_RESULT_SUCCESS_FAST) ? 1 : 0;
                res = run_agi(chan, argv[0], &agi, pid, &status, dead);
                /* If the fork'd process returns non-zero, set AGISTATUS to FAILURE */
-@@ -2062,6 +2140,8 @@ static int agi_exec_full(struct ast_chan
+@@ -2071,6 +2149,8 @@ static int agi_exec_full(struct ast_chan
                        close(fds[1]);
                if (efd > -1)
                        close(efd);
 +              if (efd2 > -1)
 +                      close(efd2);
-               ast_unreplace_sigchld();
        }
+       ast_unreplace_sigchld();
        ast_module_user_remove(u);
-@@ -2110,6 +2190,35 @@ static int eagi_exec(struct ast_channel 
+@@ -2119,6 +2199,35 @@ static int eagi_exec(struct ast_channel 
        return res;
  }
  
  static int deadagi_exec(struct ast_channel *chan, void *data)
  {
        if (!ast_check_hangup(chan))
-@@ -2165,6 +2274,7 @@ static int unload_module(void)
+@@ -2174,6 +2283,7 @@ static int unload_module(void)
  {
        ast_module_user_hangup_all();
        ast_cli_unregister_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry));
        ast_unregister_application(eapp);
        ast_unregister_application(deadapp);
        return ast_unregister_application(app);
-@@ -2175,6 +2285,7 @@ static int load_module(void)
+@@ -2184,6 +2294,7 @@ static int load_module(void)
        ast_cli_register_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry));
        ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip);
        ast_register_application(eapp, eagi_exec, esynopsis, descrip);
 +/*
 + * Asterisk -- A telephony toolkit for Linux.
 + *
-+ * XAGI sample script 
-+ * 
++ * XAGI sample script
++ *
 + * Copyright (C) 2005 Junghanns.NET GmbH
 + * Klaus-Peter Junghanns <kpj@junghanns.net>
 + *
 +
 +              /* Load into normal environment */
 +              setenv(buf, val, 1);
-+              
++
 +      }
 +      /* Never reached */
 +      return 0;
 +                      /* drop it, like it's hot */
 +              }
 +      }
-+              
++
 +}
 +
 +static char *run_command(char *command)
 @@ -0,0 +1,202 @@
 +/*
 + * Devstate application
-+ * 
++ *
 + * Since we like the snom leds so much, a little app to
 + * light the lights on the snom on demand ....
 + *
 +
 +static char descrip[] = " Devstate(device|state):  Generate a device state change event given the input parameters. Returns 0. State values match the asterisk device states. They are 0 = unknown, 1 = not inuse, 2 = inuse, 3 = busy, 4 = invalid, 5 = unavailable, 6 = ringing\n";
 +
-+static char devstate_cli_usage[] = 
-+"Usage: devstate device state\n" 
++static char devstate_cli_usage[] =
++"Usage: devstate device state\n"
 +"       Generate a device state change event given the input parameters.\n Mainly used for lighting the LEDs on the snoms.\n";
 +
 +static int devstate_cli(int fd, int argc, char *argv[]);
 +      .setoption = NULL,
 +};
 +
-+static char mandescr_devstate[] = 
++static char mandescr_devstate[] =
 +"Description: Put a value into astdb\n"
 +"Variables: \n"
 +"     Family: ...\n"
 +        ast_log(LOG_DEBUG, "Unable to register channel class %s\n", type);
 +        return -1;
 +    }
-+    ast_cli_register(&cli_dev_state);  
++    ast_cli_register(&cli_dev_state);
 +    ast_manager_register2( "Devstate", EVENT_FLAG_CALL, action_devstate, "Change a device state", mandescr_devstate );
 +    return ast_register_application(app, devstate_exec, synopsis, descrip);
 +}
 +    ast_manager_unregister( "Devstate");
 +    ast_cli_unregister(&cli_dev_state);
 +    res = ast_unregister_application(app);
-+    ast_channel_unregister(&devstate_tech);    
++    ast_channel_unregister(&devstate_tech);
 +    return res;
 +}
 +
   * This program is free software, distributed under the terms of
   * the GNU General Public License Version 2. See the LICENSE file
   * at the top of the source tree.
-@@ -3240,7 +3243,7 @@ static int iax2_hangup(struct ast_channe
+@@ -3362,7 +3365,7 @@ static int iax2_hangup(struct ast_channe
        ast_mutex_lock(&iaxsl[callno]);
        if (callno && iaxs[callno]) {
                if (option_debug)
                alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE);
                /* Send the hangup unless we have had a transmission error or are already gone */
                iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause);
-@@ -3294,7 +3297,8 @@ static int iax2_setoption(struct ast_cha
+@@ -3416,7 +3419,8 @@ static int iax2_setoption(struct ast_cha
  
  static struct ast_frame *iax2_read(struct ast_channel *c) 
  {
                        ioctl(chan->fds[0], ZT_AUDIOMODE, &x);
  
                        /* Restore saved values */
+--- a/main/channel.c
++++ b/main/channel.c
+@@ -3898,6 +3898,10 @@ enum ast_bridge_result ast_channel_bridg
+                       c1->name, c1->_bridge->name);
+               return -1;
+       }
++
++      if (IS_DIGITAL(c0->transfercapability) || IS_DIGITAL(c1->transfercapability)) {
++          config->flags = 0;
++      }
+       
+       /* Stop if we're a zombie or need a soft hangup */
+       if (ast_test_flag(c0, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c0) ||
 --- a/apps/app_meetme.c
 +++ b/apps/app_meetme.c
-@@ -1403,8 +1403,9 @@ static int conf_run(struct ast_channel *
+@@ -1405,8 +1405,9 @@ static int conf_run(struct ast_channel *
        char members[10] = "";
        int dtmf, opt_waitmarked_timeout = 0;
        time_t timeout = 0;
        char *buf = __buf + AST_FRIENDLY_OFFSET;
        int setusercount = 0;
  
-@@ -1604,7 +1605,7 @@ static int conf_run(struct ast_channel *
+@@ -1615,7 +1616,7 @@ static int conf_run(struct ast_channel *
                }
                /* Setup buffering information */
                memset(&bi, 0, sizeof(bi));
                bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
                bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
                bi.numbufs = audio_buffers;
-@@ -1913,6 +1914,14 @@ static int conf_run(struct ast_channel *
+@@ -1926,6 +1927,14 @@ static int conf_run(struct ast_channel *
                                        f = ast_read(c);
                                if (!f)
                                        break;
@@ -1943,17 +1863,17 @@ SayCharacters, SayPhonetic).
 
 --- a/main/pbx.c
 +++ b/main/pbx.c
-@@ -6060,6 +6060,9 @@ static int pbx_builtin_saynumber(struct 
+@@ -6076,6 +6076,9 @@ static int pbx_builtin_saynumber(struct 
                        return -1;
                }
        }
 +      if (chan->_state != AST_STATE_UP) {
 +          ast_answer(chan);
 +      }
-       return ast_say_number(chan, atoi(tmp), "", chan->language, options);
- }
  
-@@ -6067,8 +6070,12 @@ static int pbx_builtin_saydigits(struct 
+       if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) {
+               ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp);
+@@ -6088,8 +6091,12 @@ static int pbx_builtin_saydigits(struct 
  {
        int res = 0;
  
@@ -1967,7 +1887,7 @@ SayCharacters, SayPhonetic).
        return res;
  }
  
-@@ -6076,8 +6083,12 @@ static int pbx_builtin_saycharacters(str
+@@ -6097,8 +6104,12 @@ static int pbx_builtin_saycharacters(str
  {
        int res = 0;
  
@@ -1981,7 +1901,7 @@ SayCharacters, SayPhonetic).
        return res;
  }
  
-@@ -6085,8 +6096,12 @@ static int pbx_builtin_sayphonetic(struc
+@@ -6106,8 +6117,12 @@ static int pbx_builtin_sayphonetic(struc
  {
        int res = 0;
  
@@ -2008,7 +1928,7 @@ SayCharacters, SayPhonetic).
   * This program is free software, distributed under the terms of
   * the GNU General Public License Version 2. See the LICENSE file
   * at the top of the source tree.
-@@ -125,7 +129,8 @@ static char *descrip =
+@@ -130,7 +134,8 @@ static char *descrip =
  "    H    - Allow the calling party to hang up by hitting the '*' DTMF digit.\n"
  "    i    - Asterisk will ignore any forwarding requests it may receive on this\n"
  "           dial attempt.\n"
@@ -2018,7 +1938,7 @@ SayCharacters, SayPhonetic).
  "    k    - Allow the called party to enable parking of the call by sending\n"
  "           the DTMF sequence defined for call parking in features.conf.\n"
  "    K    - Allow the calling party to enable parking of the call by sending\n"
-@@ -1300,14 +1305,16 @@ static int dial_exec_full(struct ast_cha
+@@ -1292,14 +1297,16 @@ static int dial_exec_full(struct ast_cha
        }
  
        if (!outgoing) {
@@ -2039,7 +1959,7 @@ SayCharacters, SayPhonetic).
                        if (!ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) {
 --- a/apps/app_dial.c
 +++ b/apps/app_dial.c
-@@ -66,6 +66,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revisi
+@@ -71,6 +71,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revisi
  #include "asterisk/privacy.h"
  #include "asterisk/stringfields.h"
  #include "asterisk/global_datastores.h"
@@ -2047,7 +1967,7 @@ SayCharacters, SayPhonetic).
  
  static char *app = "Dial";
  
-@@ -1654,23 +1655,25 @@ static int dial_exec_full(struct ast_cha
+@@ -1652,23 +1653,25 @@ static int dial_exec_full(struct ast_cha
                                ast_set_flag(&(config.features_caller), AST_FEATURE_PLAY_WARNING);
                        if (play_to_callee)
                                ast_set_flag(&(config.features_callee), AST_FEATURE_PLAY_WARNING);
@@ -2084,7 +2004,7 @@ SayCharacters, SayPhonetic).
                        config.warning_freq = warning_freq;
 --- a/apps/app_dial.c
 +++ b/apps/app_dial.c
-@@ -193,6 +193,8 @@ static char *descrip =
+@@ -198,6 +198,8 @@ static char *descrip =
  "           family/key is not specified.\n"
  "    r    - Indicate ringing to the calling party. Pass no audio to the calling\n"
  "           party until the called channel has answered.\n"
@@ -2093,7 +2013,7 @@ SayCharacters, SayPhonetic).
  "    S(x) - Hang up the call after 'x' seconds *after* the called party has\n"
  "           answered the call.\n"     
  "    t    - Allow the called party to transfer the calling party by sending the\n"
-@@ -249,6 +251,7 @@ enum {
+@@ -254,6 +256,7 @@ enum {
        OPT_CALLEE_PARK =       (1 << 25),
        OPT_CALLER_PARK =       (1 << 26),
        OPT_IGNORE_FORWARDING = (1 << 27),
@@ -2101,7 +2021,7 @@ SayCharacters, SayPhonetic).
  } dial_exec_option_flags;
  
  #define DIAL_STILLGOING                       (1 << 30)
-@@ -292,6 +295,7 @@ AST_APP_OPTIONS(dial_exec_options, {
+@@ -297,6 +300,7 @@ AST_APP_OPTIONS(dial_exec_options, {
        AST_APP_OPTION('p', OPT_SCREENING),
        AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
        AST_APP_OPTION('r', OPT_RINGBACK),
@@ -2109,7 +2029,7 @@ SayCharacters, SayPhonetic).
        AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
        AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
        AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
-@@ -407,7 +411,7 @@ static struct ast_channel *wait_for_answ
+@@ -412,7 +416,7 @@ static struct ast_channel *wait_for_answ
        int orig = *to;
        struct ast_channel *peer = NULL;
        /* single is set if only one destination is enabled */
@@ -2118,7 +2038,7 @@ SayCharacters, SayPhonetic).
        
        if (single) {
                /* Turn off hold music, etc */
-@@ -628,7 +632,7 @@ static struct ast_channel *wait_for_answ
+@@ -633,7 +637,7 @@ static struct ast_channel *wait_for_answ
                                        /* Setup early media if appropriate */
                                        if (single && CAN_EARLY_BRIDGE(peerflags))
                                                ast_rtp_early_bridge(in, c);
@@ -2127,7 +2047,7 @@ SayCharacters, SayPhonetic).
                                                ast_indicate(in, AST_CONTROL_PROGRESS);
                                        break;
                                case AST_CONTROL_VIDUPDATE:
-@@ -641,7 +645,7 @@ static struct ast_channel *wait_for_answ
+@@ -651,7 +655,7 @@ static struct ast_channel *wait_for_answ
                                                ast_verbose (VERBOSE_PREFIX_3 "%s is proceeding passing it to %s\n", c->name, in->name);
                                        if (single && CAN_EARLY_BRIDGE(peerflags))
                                                ast_rtp_early_bridge(in, c);
@@ -2136,7 +2056,7 @@ SayCharacters, SayPhonetic).
                                                ast_indicate(in, AST_CONTROL_PROCEEDING);
                                        break;
                                case AST_CONTROL_HOLD:
-@@ -659,7 +663,7 @@ static struct ast_channel *wait_for_answ
+@@ -669,7 +673,7 @@ static struct ast_channel *wait_for_answ
                                        /* Ignore going off hook and flash */
                                        break;
                                case -1:
@@ -2145,7 +2065,7 @@ SayCharacters, SayPhonetic).
                                                if (option_verbose > 2)
                                                        ast_verbose(VERBOSE_PREFIX_3 "%s stopped sounds\n", c->name);
                                                ast_indicate(in, -1);
-@@ -1099,7 +1103,7 @@ static int dial_exec_full(struct ast_cha
+@@ -1091,7 +1095,7 @@ static int dial_exec_full(struct ast_cha
                outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP");
        }
            
@@ -2154,7 +2074,7 @@ SayCharacters, SayPhonetic).
        /* loop through the list of dial destinations */
        rest = args.peers;
        while ((cur = strsep(&rest, "&")) ) {
-@@ -1124,7 +1128,7 @@ static int dial_exec_full(struct ast_cha
+@@ -1116,7 +1120,7 @@ static int dial_exec_full(struct ast_cha
                                       OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
                                       OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
                                       OPT_CALLEE_PARK | OPT_CALLER_PARK |
@@ -2163,7 +2083,7 @@ SayCharacters, SayPhonetic).
                        ast_set2_flag(tmp, args.url, DIAL_NOFORWARDHTML);       
                }
                ast_copy_string(numsubst, number, sizeof(numsubst));
-@@ -1327,7 +1331,7 @@ static int dial_exec_full(struct ast_cha
+@@ -1319,7 +1323,7 @@ static int dial_exec_full(struct ast_cha
                                ast_moh_start(chan, NULL, NULL);
                        }
                        ast_indicate(chan, AST_CONTROL_PROGRESS);
@@ -2172,7 +2092,7 @@ SayCharacters, SayPhonetic).
                        ast_indicate(chan, AST_CONTROL_RINGING);
                        sentringing++;
                }
-@@ -1444,7 +1448,7 @@ static int dial_exec_full(struct ast_cha
+@@ -1442,7 +1446,7 @@ static int dial_exec_full(struct ast_cha
  
                        if (ast_test_flag(&opts, OPT_MUSICBACK)) {
                                ast_moh_stop(chan);
@@ -2183,7 +2103,7 @@ SayCharacters, SayPhonetic).
                        }
 --- a/apps/app_dial.c
 +++ b/apps/app_dial.c
-@@ -196,7 +196,8 @@ static char *descrip =
+@@ -201,7 +201,8 @@ static char *descrip =
  "    R          - indicate ringing to the calling party when the called party indicates\n"
  "            ringing, pass no audio until answered.\n"
  "    S(x) - Hang up the call after 'x' seconds *after* the called party has\n"
@@ -2193,7 +2113,7 @@ SayCharacters, SayPhonetic).
  "    t    - Allow the called party to transfer the calling party by sending the\n"
  "           DTMF sequence defined in features.conf.\n"
  "    T    - Allow the calling party to transfer the called party by sending the\n"
-@@ -252,6 +253,7 @@ enum {
+@@ -257,6 +258,7 @@ enum {
        OPT_CALLER_PARK =       (1 << 26),
        OPT_IGNORE_FORWARDING = (1 << 27),
        OPT_NOINBAND =          (1 << 28),
@@ -2201,7 +2121,7 @@ SayCharacters, SayPhonetic).
  } dial_exec_option_flags;
  
  #define DIAL_STILLGOING                       (1 << 30)
-@@ -296,6 +298,7 @@ AST_APP_OPTIONS(dial_exec_options, {
+@@ -301,6 +303,7 @@ AST_APP_OPTIONS(dial_exec_options, {
        AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
        AST_APP_OPTION('r', OPT_RINGBACK),
        AST_APP_OPTION('R', OPT_NOINBAND),
@@ -2209,7 +2129,7 @@ SayCharacters, SayPhonetic).
        AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
        AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
        AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
-@@ -616,14 +619,20 @@ static struct ast_channel *wait_for_answ
+@@ -621,14 +624,20 @@ static struct ast_channel *wait_for_answ
                                        HANDLE_CAUSE(AST_CAUSE_CONGESTION, in);
                                        break;
                                case AST_CONTROL_RINGING:
@@ -2234,7 +2154,7 @@ SayCharacters, SayPhonetic).
                                        }
                                        break;
                                case AST_CONTROL_PROGRESS:
-@@ -1103,7 +1112,7 @@ static int dial_exec_full(struct ast_cha
+@@ -1095,7 +1104,7 @@ static int dial_exec_full(struct ast_cha
                outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP");
        }
            
@@ -2243,5535 +2163,4787 @@ SayCharacters, SayPhonetic).
        /* loop through the list of dial destinations */
        rest = args.peers;
        while ((cur = strsep(&rest, "&")) ) {
+# Allow as many spans as Zaptel can take (defualt: 128).
+# There is a static array of zt_pris allocated at this size.
+# For that reason upstream only sort-of merged it: made it a
+# compile-time option in 1.6 .
+
 --- a/channels/chan_zap.c
 +++ b/channels/chan_zap.c
-@@ -104,6 +104,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revisi
- #include "asterisk/abstract_jb.h"
- #include "asterisk/smdi.h"
- #include "asterisk/astobj.h"
-+#include "asterisk/devicestate.h"
-+
- #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
- /*! Global jitterbuffer configuration - by default, jb is disabled */
-@@ -703,6 +705,7 @@ static const struct ast_channel_tech zap
-       .fixup = zt_fixup,
-       .setoption = zt_setoption,
-       .func_channel_read = zt_func_read,
-+/*    .devicestate = zt_devicestate, */
- };
+@@ -190,7 +190,7 @@ static const char config[] = "zapata.con
+ #define SIG_GR303FXOKS        (0x0100000 | ZT_SIG_FXOKS)
+ #define SIG_GR303FXSKS        (0x0100000 | ZT_SIG_FXSKS)
  
- #ifdef HAVE_PRI
-@@ -761,6 +764,112 @@ static int cidrings[NUM_CADENCE_MAX] = {
- #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __ZT_SIG_FXO) */)
- #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __ZT_SIG_FXO) */)
+-#define NUM_SPANS             32
++#define NUM_SPANS             ZT_MAX_SPANS
+ #define NUM_DCHANS            4       /*!< No more than 4 d-channels */
+ #define MAX_CHANNELS  672             /*!< No more than a DS3 per trunk group */
  
-+static int zt_devicestate(void *data)
-+{
-+      int groupmatch = 0;
-+      int channelmatch = 0;
-+      struct zt_pvt *p;
-+      char *dest=NULL;
-+      int x;
-+      char *s;
-+      char opt=0;
-+      int res, y=0;
-+      struct zt_pvt *exit, *start, *end;
-+      ast_mutex_t *lock;
-+
-+//    ast_log(LOG_NOTICE, "data = %s\n", (char *)data);
-+      return AST_DEVICE_UNKNOWN;
-+      
-+      /* Assume we're locking the iflock */
-+      lock = &iflock;
-+      start = iflist;
-+      end = ifend;
-+
-+      if (data) {
-+              dest = ast_strdupa((char *)data);
-+      } else {
-+              ast_log(LOG_WARNING, "Channel requested with no data\n");
-+              return AST_DEVICE_INVALID;
-+      }
-+      if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
-+              /* Retrieve the group number */
-+              char *stringp=NULL;
-+              stringp=dest + 1;
-+              s = strsep(&stringp, "/");
-+              if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
-+                      ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
-+                      return AST_DEVICE_INVALID;
-+              }
-+              groupmatch = 1 << x;
-+      } else {
-+              char *stringp=NULL;
-+              stringp=dest;
-+              s = strsep(&stringp, "/");
-+              p = iflist;
-+              if (!strcasecmp(s, "pseudo")) {
-+                      /* Special case for pseudo */
-+                      x = CHAN_PSEUDO;
-+                      channelmatch = x;
-+                      /* bail out */
-+                      return AST_DEVICE_INVALID;
-+              } 
-+
-+              else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
-+                      ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
-+                      return AST_DEVICE_INVALID;
-+              } else {
-+                      channelmatch = x;
-+                      ast_log(LOG_NOTICE, "channelmatch = %d\n", channelmatch);
-+              }
-+      }
-+      /* Search for an unowned channel */
-+      if (ast_mutex_lock(lock)) {
-+              ast_log(LOG_ERROR, "Unable to lock interface list???\n");
-+              return AST_DEVICE_INVALID;
-+      }
-+      p = iflist;
-+      exit = iflist;
-+      res = AST_DEVICE_INVALID; /* start pessimistic */
-+      while(p) {
-+              if (p) {
-+                  ast_mutex_lock(&p->lock);
-+                  if ((groupmatch && ((p->group & groupmatch) != 0)) || (channelmatch && (p->channel == channelmatch))) {
-+#ifdef ZAPATA_PRI
-+                      if (p->pri) {
-+                          for(d=0;d<NUM_DCHANS;d++) {
-+                              if (p->pri->dchanavail[d] & DCHAN_UP) {
-+                                  res = AST_DEVICE_UNKNOWN;
-+                              }
-+                          }
-+                      }
-+#endif
-+                      if ((!ast_strlen_zero(p->cid_num) && (strncasecmp(p->cid_num, dest, strlen(p->cid_num)))) || (!ast_strlen_zero(p->dnid) && (strncasecmp(p->dnid, dest, strlen(p->dnid))))) {
-+                          res = AST_DEVICE_UNKNOWN;
-+                          if (p->owner) {
-+                                  if ((p->owner->_state == AST_STATE_RINGING) && (p->outgoing)) {
-+                                      res = AST_DEVICE_RINGING;
-+                                  }
-+                                  if (((p->owner->_state == AST_STATE_RINGING) && (!p->outgoing)) || (p->owner->_state == AST_STATE_UP) || (p->owner->_state == AST_STATE_DIALING) || (p->owner->_state == AST_STATE_RESERVED) || (p->owner->_state == AST_STATE_RING)){
-+                                      res = AST_DEVICE_INUSE;
-+                                  }
-+                          }
-+                          if ((res == AST_DEVICE_INUSE) || (res == AST_DEVICE_RINGING)) {
-+                              /* stop searching now, one non-idle channel is sufficient */
-+                              ast_mutex_unlock(&p->lock);
-+                              break;
-+                          }
-+                      }
-+                  }
-+                  ast_mutex_unlock(&p->lock);
-+              }       
-+              p = p->next;
-+      }
-+      ast_mutex_unlock(lock);
-+
-+      return res;
-+
-+}
-+
- static int zt_get_index(struct ast_channel *ast, struct zt_pvt *p, int nullok)
- {
-       int res;
-Change the API of ast_sendtext and chan->sendtext to add dest and ispdu
-parameters, used by ast_send_message which is also introduced by this patch.
-
 --- a/include/asterisk/channel.h
 +++ b/include/asterisk/channel.h
-@@ -227,7 +227,7 @@ struct ast_channel_tech {
-       int (* const write)(struct ast_channel *chan, struct ast_frame *frame);
-       /*! \brief Display or transmit text */
--      int (* const send_text)(struct ast_channel *chan, const char *text);
-+      int (* const send_text)(struct ast_channel *chan, const char *dest, const char *text, int ispdu);
-       /*! \brief Display or send an image */
-       int (* const send_image)(struct ast_channel *chan, struct ast_frame *frame);
-@@ -671,6 +671,16 @@ struct ast_channel *ast_request_and_dial
- struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, const char *cidnum, const char *cidname, struct outgoing_helper *oh);
-+/*! \brief "Requests" a channel for sending a message
-+ * \param type type of channel to request
-+ * \param data data to pass to the channel requester
-+ * \param status status
-+ * Request a channel of a given type, with data as optional information used 
-+ * by the low level module
-+ * \return Returns 0 on success, -1 on failure.
-+ */
-+int ast_send_message(const char *type, void *data, char *to, char *from, char *message, int ispdu);
-+ 
- /*!\brief Register a channel technology (a new channel driver)
-  * Called by a channel module to register the kind of channels it supports.
-  * \param tech Structure defining channel technology or "type"
-@@ -887,10 +897,12 @@ int ast_set_write_format(struct ast_chan
- /*! \brief Sends text to a channel 
-  * Write text to a display on a channel
-  * \param chan channel to act upon
-+ * \param dest destination number/user
-  * \param text string of text to send on the channel
-+ * \param ispdu message is in PDU format
-  * \return Returns 0 on success, -1 on failure
-  */
--int ast_sendtext(struct ast_channel *chan, const char *text);
-+int ast_sendtext(struct ast_channel *chan, const char *dest, const char *text, int ispdu);
- /*! \brief Receives a text character from a channel
-  * \param chan channel to act upon
---- a/main/channel.c
-+++ b/main/channel.c
-@@ -2694,7 +2694,7 @@ char *ast_recvtext(struct ast_channel *c
-       return buf;
- }
--int ast_sendtext(struct ast_channel *chan, const char *text)
-+int ast_sendtext(struct ast_channel *chan, const char *dest, const char *text, int ispdu)
- {
-       int res = 0;
-       /* Stop if we're a zombie or need a soft hangup */
-@@ -2702,7 +2702,7 @@ int ast_sendtext(struct ast_channel *cha
-               return -1;
-       CHECK_BLOCKING(chan);
-       if (chan->tech->send_text)
--              res = chan->tech->send_text(chan, text);
-+              res = chan->tech->send_text(chan, dest, text, ispdu);
-       ast_clear_flag(chan, AST_FLAG_BLOCKING);
-       return res;
- }
-@@ -2881,7 +2881,7 @@ int ast_write(struct ast_channel *chan, 
-               break;
-       case AST_FRAME_TEXT:
-               res = (chan->tech->send_text == NULL) ? 0 :
--                      chan->tech->send_text(chan, (char *) fr->data);
-+                      chan->tech->send_text(chan, NULL, (char *) fr->data, 0);
-               break;
-       case AST_FRAME_HTML:
-               res = (chan->tech->send_html == NULL) ? 0 :
-@@ -4908,6 +4908,25 @@ void ast_channel_stop_silence_generator(
- }
-+int ast_send_message(const char *type, void *data, char *to, char *from, char *message, int ispdu) {
-+      struct ast_channel *chan = NULL;
-+      int status;
-+      int res = -1;
-+
-+      chan = ast_request(type, AST_FORMAT_SLINEAR, data, &status);
-+      if (chan) {
-+          if (from) {
-+              ast_set_callerid(chan, from, from, from);
-+          }
-+          res = ast_sendtext(chan, to, message, ispdu);
-+          /* XXX what about message CDRs ??? XXX */
-+          ast_hangup(chan);
-+          return res;
-+      }
-+
-+      return res;
-+}
-+
- /*! \ brief Convert channel reloadreason (ENUM) to text string for manager event */
- const char *channelreloadreason2txt(enum channelreloadreason reason)
- {
---- a/apps/app_sendtext.c
-+++ b/apps/app_sendtext.c
-@@ -103,7 +103,7 @@ static int sendtext_exec(struct ast_chan
-       }
-       status = "FAILURE";
-       ast_channel_unlock(chan);
--      res = ast_sendtext(chan, args.text);
-+      res = ast_sendtext(chan, NULL, args.text, 0);
-       if (!res)
-               status = "SUCCESS";
-       pbx_builtin_setvar_helper(chan, "SENDTEXTSTATUS", status);
---- a/res/res_agi.c
-+++ b/res/res_agi.c
-@@ -486,7 +486,7 @@ static int handle_sendtext(struct ast_ch
-          would probably be to strip off the trailing newline before
-          parsing, then here, add a newline at the end of the string
-          before sending it to ast_sendtext --DUDE */
--      res = ast_sendtext(chan, argv[2]);
-+      res = ast_sendtext(chan, NULL, argv[2], 0);
-       fdprintf(agi->fd, "200 result=%d\n", res);
-       return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
- }
---- a/channels/chan_agent.c
-+++ b/channels/chan_agent.c
-@@ -246,7 +246,7 @@ static int agent_answer(struct ast_chann
- static struct ast_frame *agent_read(struct ast_channel *ast);
- static int agent_write(struct ast_channel *ast, struct ast_frame *f);
- static int agent_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen);
--static int agent_sendtext(struct ast_channel *ast, const char *text);
-+static int agent_sendtext(struct ast_channel *ast, const char *dest, const char *text, int ispdu);
- static int agent_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
- static int agent_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
- static struct ast_channel *agent_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge);
-@@ -555,13 +555,13 @@ static int agent_sendhtml(struct ast_cha
-       return res;
- }
--static int agent_sendtext(struct ast_channel *ast, const char *text)
-+static int agent_sendtext(struct ast_channel *ast, const char *dest, const char *text, int ispdu)
- {
-       struct agent_pvt *p = ast->tech_pvt;
-       int res = -1;
-       ast_mutex_lock(&p->lock);
-       if (p->chan) 
--              res = ast_sendtext(p->chan, text);
-+              res = ast_sendtext(p->chan, dest, text, ispdu);
-       ast_mutex_unlock(&p->lock);
-       return res;
- }
---- a/channels/chan_alsa.c
-+++ b/channels/chan_alsa.c
-@@ -186,7 +186,7 @@ static int nosound = 0;
- /* ZZ */
- static struct ast_channel *alsa_request(const char *type, int format, void *data, int *cause);
- static int alsa_digit(struct ast_channel *c, char digit, unsigned int duration);
--static int alsa_text(struct ast_channel *c, const char *text);
-+static int alsa_text(struct ast_channel *c, const char *dest, const char *text, int ispdu);
- static int alsa_hangup(struct ast_channel *c);
- static int alsa_answer(struct ast_channel *c);
- static struct ast_frame *alsa_read(struct ast_channel *chan);
-@@ -496,7 +496,7 @@ static int alsa_digit(struct ast_channel
-       return 0;
- }
--static int alsa_text(struct ast_channel *c, const char *text)
-+static int alsa_text(struct ast_channel *c, const char *dest, const char *text, int ispdu)
- {
-       ast_mutex_lock(&alsalock);
-       ast_verbose(" << Console Received text %s >> \n", text);
---- a/channels/chan_local.c
-+++ b/channels/chan_local.c
-@@ -77,7 +77,7 @@ static int local_write(struct ast_channe
- static int local_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
- static int local_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
- static int local_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen);
--static int local_sendtext(struct ast_channel *ast, const char *text);
-+static int local_sendtext(struct ast_channel *ast, const char *dest, const char *text, int ispdu);
- static int local_devicestate(void *data);
- /* PBX interface structure for channel registration */
-@@ -390,7 +390,7 @@ static int local_digit_end(struct ast_ch
-       return res;
- }
--static int local_sendtext(struct ast_channel *ast, const char *text)
-+static int local_sendtext(struct ast_channel *ast, const char *dest, const char *text, int ispdu)
- {
-       struct local_pvt *p = ast->tech_pvt;
-       int res = -1;
---- a/channels/chan_oss.c
-+++ b/channels/chan_oss.c
-@@ -405,7 +405,7 @@ static struct ast_channel *oss_request(c
- , int *cause);
- static int oss_digit_begin(struct ast_channel *c, char digit);
- static int oss_digit_end(struct ast_channel *c, char digit, unsigned int duration);
--static int oss_text(struct ast_channel *c, const char *text);
-+static int oss_text(struct ast_channel *c, const char *dest, const char *text, int ispdu);
- static int oss_hangup(struct ast_channel *c);
- static int oss_answer(struct ast_channel *c);
- static struct ast_frame *oss_read(struct ast_channel *chan);
-@@ -773,7 +773,7 @@ static int oss_digit_end(struct ast_chan
-       return 0;
- }
--static int oss_text(struct ast_channel *c, const char *text)
-+static int oss_text(struct ast_channel *c, const char *dest, const char *text, int ispdu)
- {
-       /* print received messages */
-       ast_verbose(" << Console Received text %s >> \n", text);
---- a/channels/chan_phone.c
-+++ b/channels/chan_phone.c
-@@ -166,7 +166,7 @@ static int phone_answer(struct ast_chann
- static struct ast_frame *phone_read(struct ast_channel *ast);
- static int phone_write(struct ast_channel *ast, struct ast_frame *frame);
- static struct ast_frame *phone_exception(struct ast_channel *ast);
--static int phone_send_text(struct ast_channel *ast, const char *text);
-+static int phone_send_text(struct ast_channel *ast, const char *dest, const char *text, int ispdu);
- static int phone_fixup(struct ast_channel *old, struct ast_channel *new);
- static int phone_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
-@@ -640,7 +640,7 @@ static int phone_write_buf(struct phone_
-       return len;
- }
--static int phone_send_text(struct ast_channel *ast, const char *text)
-+static int phone_send_text(struct ast_channel *ast, const char *dest, const char *text, int ispdu)
- {
-     int length = strlen(text);
-     return phone_write_buf(ast->tech_pvt, text, length, length, 0) == 
---- a/channels/chan_sip.c
-+++ b/channels/chan_sip.c
-@@ -1215,7 +1215,7 @@ static struct ast_config *notify_types;  
- /*--- PBX interface functions */
- static struct ast_channel *sip_request_call(const char *type, int format, void *data, int *cause);
- static int sip_devicestate(void *data);
--static int sip_sendtext(struct ast_channel *ast, const char *text);
-+static int sip_sendtext(struct ast_channel *ast, const char *dest, const char *text, int ispdu);
- static int sip_call(struct ast_channel *ast, char *dest, int timeout);
- static int sip_hangup(struct ast_channel *ast);
- static int sip_answer(struct ast_channel *ast);
-@@ -2347,7 +2347,7 @@ static char *get_in_brackets(char *tmp)
- /*! \brief Send SIP MESSAGE text within a call
-       Called from PBX core sendtext() application */
--static int sip_sendtext(struct ast_channel *ast, const char *text)
-+static int sip_sendtext(struct ast_channel *ast, const char *dest, const char *text, int ispdu)
- {
-       struct sip_pvt *p = ast->tech_pvt;
-       int debug = sip_debug_test_pvt(p);
---- a/channels/chan_iax2.c
-+++ b/channels/chan_iax2.c
-@@ -831,7 +831,7 @@ static int iax2_provision(struct sockadd
- static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned int ts, int seqno, int now, int transfer, int final);
- static int iax2_sendhtml(struct ast_channel *c, int subclass, const char *data, int datalen);
- static int iax2_sendimage(struct ast_channel *c, struct ast_frame *img);
--static int iax2_sendtext(struct ast_channel *c, const char *text);
-+static int iax2_sendtext(struct ast_channel *c, const char *dest, const char *text, int ispdu);
- static int iax2_setoption(struct ast_channel *c, int option, void *data, int datalen);
- static int iax2_transfer(struct ast_channel *c, const char *dest);
- static int iax2_write(struct ast_channel *c, struct ast_frame *f);
-@@ -2642,7 +2642,7 @@ static int iax2_digit_end(struct ast_cha
-       return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_END, digit, 0, NULL, 0, -1);
- }
+@@ -435,6 +435,7 @@ struct ast_channel {
+       unsigned int flags;                             /*!< channel flags of AST_FLAG_ type */
+       unsigned short transfercapability;              /*!< ISDN Transfer Capbility - AST_FLAG_DIGITAL is not enough */
+       AST_LIST_HEAD_NOLOCK(, ast_frame) readq;
++      char lowlayercompat[16];                        /*!< ISDN Low Layer Compatibility */
+       int alertpipe[2];
  
--static int iax2_sendtext(struct ast_channel *c, const char *text)
-+static int iax2_sendtext(struct ast_channel *c, const char *dest, const char *text, int ispdu)
- {
-       
-       return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_TEXT,
---- a/main/manager.c
-+++ b/main/manager.c
-@@ -11,6 +11,9 @@
+       int nativeformats;                              /*!< Kinds of data this channel can natively handle */
+--- a/channels/chan_zap.c
++++ b/channels/chan_zap.c
+@@ -11,6 +11,10 @@
   * the project provides a web site, mailing lists and IRC
   * channels for your use.
   *
-+ * Copyright (C) 2003-2004, Junghanns.NET Gmbh
++ * Copyright (C) 2003-2006 Junghanns.NET GmbH
 + * Klaus-Peter Junghanns <kpj@junghanns.net>
++ *
 + *
   * This program is free software, distributed under the terms of
   * the GNU General Public License Version 2. See the LICENSE file
   * at the top of the source tree.
-@@ -1426,6 +1429,49 @@ static int action_hangup(struct mansessi
-       return 0;
- }
+@@ -216,8 +220,6 @@ static struct ast_channel inuse;
+ #ifdef PRI_GETSET_TIMERS
+ static int pritimers[PRI_MAX_TIMERS];
+ #endif
+-static int pridebugfd = -1;
+-static char pridebugfilename[1024] = "";
+ #endif
  
-+static char mandescr_message[] = 
-+"Description: Send a message\n"
-+"Variables: \n"
-+"     Channel: The destination channel(e.g. SIP/phone1)\n"
-+"     From:    \n"
-+"     Message: The message to send\n";
-+
-+static int action_message(struct mansession *s, const struct message *m)
-+{
-+      const char *name = astman_get_header(m, "Channel");
-+      const char *from = astman_get_header(m, "From");
-+      const char *message = astman_get_header(m, "Message");
-+      const char *pdu = astman_get_header(m, "PDU");
-+      char tmp[256];
-+      char *tech, *data;
-+      int res;
-+      if (ast_strlen_zero(name) || (ast_strlen_zero(message) && ast_strlen_zero(pdu))) {
-+              astman_send_error(s, m, "No channel or message/PDU specified");
-+              return 0;
-+      }
-+      ast_copy_string(tmp, name, sizeof(tmp));
-+      tech = tmp;
-+      data = strchr(tmp, '/');
-+      if (!data) {
-+              astman_send_error(s, m, "Invalid channel\n");
-+              return 0;
-+      }
-+      *data = '\0';
-+      data++;
-+      if (ast_strlen_zero(pdu)) {
-+          res = ast_send_message(tech, (char *)data, (char *)name, (char *)from, (char *)message, 0);
-+      } else {
-+          res = ast_send_message(tech, (char *)data, (char *)name, (char *)from, (char *)pdu, 1);
-+      }
-+      
-+      if (res) {
-+              astman_send_error(s, m, "Error sending message");
-+              return 0;
-+      }
-+      astman_send_ack(s, m, "Message sent");
-+      return 0;
-+}
-+
- static char mandescr_setvar[] = 
- "Description: Set a global or local channel variable.\n"
- "Variables: (Names marked with * are required)\n"
-@@ -2835,6 +2881,7 @@ int init_manager(void)
-               ast_manager_register2("Events", 0, action_events, "Control Event Flow", mandescr_events);
-               ast_manager_register2("Logoff", 0, action_logoff, "Logoff Manager", mandescr_logoff);
-               ast_manager_register2("Hangup", EVENT_FLAG_CALL, action_hangup, "Hangup Channel", mandescr_hangup);
-+              ast_manager_register2("Message", EVENT_FLAG_CALL, action_message, "Send Message", mandescr_message);
-               ast_manager_register("Status", EVENT_FLAG_CALL, action_status, "Lists channel status" );
-               ast_manager_register2("Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable", mandescr_setvar );
-               ast_manager_register2("Getvar", EVENT_FLAG_CALL, action_getvar, "Gets a Channel Variable", mandescr_getvar );
---- a/pbx/pbx_spool.c
-+++ b/pbx/pbx_spool.c
-@@ -87,6 +87,10 @@ struct outgoing {
-       char app[256];
-       char data[256];
+ /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
+@@ -235,10 +237,6 @@ AST_MUTEX_DEFINE_STATIC(iflock);
  
-+      /* If SMS */
-+      char message[256];
-+      char pdu[256];
-+
-       /* If extension/context/priority */
-       char exten[256];
-       char context[256];
-@@ -181,6 +185,10 @@ static int apply_outgoing(struct outgoin
-                                       ast_copy_string(o->app, c, sizeof(o->app));
-                               } else if (!strcasecmp(buf, "data")) {
-                                       ast_copy_string(o->data, c, sizeof(o->data));
-+                              } else if (!strcasecmp(buf, "message")) {
-+                                      strncpy(o->message, c, sizeof(o->message) - 1);
-+                              } else if (!strcasecmp(buf, "pdu")) {
-+                                      strncpy(o->pdu, c, sizeof(o->pdu) - 1);
-                               } else if (!strcasecmp(buf, "maxretries")) {
-                                       if (sscanf(c, "%d", &o->maxretries) != 1) {
-                                               ast_log(LOG_WARNING, "Invalid max retries at line %d of %s\n", lineno, fn);
-@@ -241,8 +249,8 @@ static int apply_outgoing(struct outgoin
-               }
-       }
-       ast_copy_string(o->fn, fn, sizeof(o->fn));
--      if (ast_strlen_zero(o->tech) || ast_strlen_zero(o->dest) || (ast_strlen_zero(o->app) && ast_strlen_zero(o->exten))) {
--              ast_log(LOG_WARNING, "At least one of app or extension must be specified, along with tech and dest in file %s\n", fn);
-+      if (ast_strlen_zero(o->tech) || ast_strlen_zero(o->dest) || ((ast_strlen_zero(o->app) && ast_strlen_zero(o->exten) && ast_strlen_zero(o->message) && ast_strlen_zero(o->pdu)))) {
-+              ast_log(LOG_WARNING, "At least one of app or extension (or keyword message/pdu)must be specified, along with tech and dest in file %s\n", fn);
-               return -1;
-       }
-       return 0;
-@@ -332,6 +340,14 @@ static void *attempt_thread(void *data)
-               if (option_verbose > 2)
-                       ast_verbose(VERBOSE_PREFIX_3 "Attempting call on %s/%s for application %s(%s) (Retry %d)\n", o->tech, o->dest, o->app, o->data, o->retries);
-               res = ast_pbx_outgoing_app(o->tech, AST_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->app, o->data, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL);
-+      } else if (!ast_strlen_zero(o->message)) {
-+              if (option_verbose > 2)
-+                      ast_verbose(VERBOSE_PREFIX_3 "Attempting to send message on %s/%s (Retry %d)\n", o->tech, o->dest, o->retries);
-+              res = ast_send_message(o->tech, o->dest, o->dest, (ast_strlen_zero(o->cid_name) ? o->cid_num : o->cid_name), o->message, 0);
-+      } else if (!ast_strlen_zero(o->pdu)) {
-+              if (option_verbose > 2)
-+                      ast_verbose(VERBOSE_PREFIX_3 "Attempting to send message in PDU format on %s/%s (Retry %d)\n", o->tech, o->dest, o->retries);
-+              res = ast_send_message(o->tech, o->dest, o->dest, (ast_strlen_zero(o->cid_name) ? o->cid_num : o->cid_name), o->pdu, 1);
-       } else {
-               if (option_verbose > 2)
-                       ast_verbose(VERBOSE_PREFIX_3 "Attempting call on %s/%s for %s@%s:%d (Retry %d)\n", o->tech, o->dest, o->exten, o->context,o->priority, o->retries);
-@@ -348,9 +364,14 @@ static void *attempt_thread(void *data)
-                       safe_append(o, time(NULL), "EndRetry");
-               }
-       } else {
-+          if (!ast_strlen_zero(o->message)) {
-+              if (option_verbose > 2)
-+                  ast_verbose(VERBOSE_PREFIX_2 "Message sent to %s/%s\n", o->tech, o->dest);
-+          } else {
-               ast_log(LOG_NOTICE, "Call completed to %s/%s\n", o->tech, o->dest);
-               ast_log(LOG_EVENT, "Queued call to %s/%s completed\n", o->tech, o->dest);
--              remove_from_queue(o, "Completed");
-+          }
-+          remove_from_queue(o, "Completed");
-       }
-       free_outgoing(o);
-       return NULL;
---- a/include/asterisk/monitor.h
-+++ b/include/asterisk/monitor.h
-@@ -38,6 +38,8 @@ struct ast_channel_monitor {
-       char write_filename[FILENAME_MAX];
-       char filename_base[FILENAME_MAX];
-       int filename_changed;
-+      char target_url[FILENAME_MAX];
-+      char target_script[FILENAME_MAX];
-       char *format;
-       int joinfiles;
-       enum AST_MONITORING_STATE state;
-@@ -46,7 +48,7 @@ struct ast_channel_monitor {
+ static int ifcount = 0;
  
- /* Start monitoring a channel */
- int ast_monitor_start(struct ast_channel *chan, const char *format_spec,
--                    const char *fname_base, int need_lock );
-+                    const char *fname_base, const char *target_url, const char *target_script, int need_lock );
+-#ifdef HAVE_PRI
+-AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
+-#endif
+-
+ /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
+    when it's doing something critical. */
+ AST_MUTEX_DEFINE_STATIC(monlock);
+@@ -253,6 +251,7 @@ static enum ast_bridge_result zt_bridge(
  
- /* Stop monitoring a channel */
- int ast_monitor_stop(struct ast_channel *chan, int need_lock);
---- a/res/res_monitor.c
-+++ b/res/res_monitor.c
-@@ -129,7 +129,7 @@ static int ast_monitor_set_state(struct 
+ static int zt_sendtext(struct ast_channel *c, const char *text);
  
- /* Start monitoring a channel */
- int ast_monitor_start(        struct ast_channel *chan, const char *format_spec,
--              const char *fname_base, int need_lock)
-+              const char *fname_base, const char *target_url, const char *target_script, int need_lock)
++
+ /*! \brief Avoid the silly zt_getevent which ignores a bunch of events */
+ static inline int zt_get_event(int fd)
  {
-       int res = 0;
-       char tmp[256];
-@@ -153,6 +153,11 @@ int ast_monitor_start(    struct ast_channe
-                       return -1;
-               }
+@@ -297,6 +296,14 @@ static int ringt_base = DEFAULT_RINGT;
+ #define PRI_SPAN(p) (((p) >> 8) & 0xff)
+ #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
  
-+              if (target_url)
-+                  ast_copy_string(monitor->target_url, target_url, sizeof(monitor->target_url));
-+              if (target_script)
-+                  ast_copy_string(monitor->target_script, target_script, sizeof(monitor->target_script));
++struct zt_suspended_call {
++      ast_mutex_t lock;               /* Mutex */
++      char msn[AST_MAX_EXTENSION];    /* the MSN to which this parked call belongs */
++      char callid[10];                        /* the callID provided by the user */
++      int parked_at;                  /* extension in the call parking context */
++      struct zt_suspended_call *next;
++};
 +
-               /* Determine file names */
-               if (!ast_strlen_zero(fname_base)) {
-                       int directory = strchr(fname_base, '/') ? 1 : 0;
-@@ -295,6 +300,8 @@ int ast_monitor_stop(struct ast_channel 
-               if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) {
-                       char tmp[1024];
-                       char tmp2[1024];
-+                      char tmp3[1024];
-+                      int result;
-                       const char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format;
-                       char *name = chan->monitor->filename_base;
-                       int directory = strchr(name, '/') ? 1 : 0;
-@@ -322,8 +329,13 @@ int ast_monitor_stop(struct ast_channel 
-                               snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s/%s-\"* ) &",tmp, dir ,name); /* remove legs when done mixing */
-                               ast_copy_string(tmp, tmp2, sizeof(tmp));
-                       }
--                      ast_log(LOG_DEBUG,"monitor executing %s\n",tmp);
--                      if (ast_safe_system(tmp) == -1)
-+                      if (!ast_strlen_zero(chan->monitor->target_script) && !ast_strlen_zero(chan->monitor->target_url)) {
-+                              snprintf(tmp3,sizeof(tmp3), "( %s& nice -19 %s \"%s/%s.%s\" \"%s\" ) &",tmp, chan->monitor->target_script , dir, name, format, chan->monitor->target_url); 
-+                              ast_copy_string(tmp, tmp3, sizeof(tmp));
-+                      }
-+                      ast_log(LOG_NOTICE,"monitor executing %s\n",tmp);
-+                      result = ast_safe_system(tmp);
-+                      if (result == -1)
-                               ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
-               }
-               
-@@ -452,7 +464,7 @@ static int start_monitor_exec(struct ast
-               return 0;
-       }
--      res = ast_monitor_start(chan, format, fname_base, 1);
-+      res = ast_monitor_start(chan, format, fname_base, NULL, NULL, 1);
-       if (res < 0)
-               res = ast_monitor_change_fname(chan, fname_base, 1);
-       ast_monitor_setjoinfiles(chan, joinfiles);
-@@ -491,6 +503,8 @@ static int start_monitor_action(struct m
-       const char *fname = astman_get_header(m, "File");
-       const char *format = astman_get_header(m, "Format");
-       const char *mix = astman_get_header(m, "Mix");
-+      const char *target_url = astman_get_header(m, "TargetURL");
-+      const char *target_script = astman_get_header(m, "TargetScript");
-       char *d;
-       
-       if (ast_strlen_zero(name)) {
-@@ -515,7 +529,7 @@ static int start_monitor_action(struct m
-                       *d = '-';
-       }
-       
--      if (ast_monitor_start(c, format, fname, 1)) {
-+      if (ast_monitor_start(c, format, fname, target_url, target_script, 1)) {
-               if (ast_monitor_change_fname(c, fname, 1)) {
-                       astman_send_error(s, m, "Could not start monitoring channel");
-                       ast_channel_unlock(c);
---- a/apps/app_queue.c
-+++ b/apps/app_queue.c
-@@ -2804,13 +2804,13 @@ static int try_calling(struct queue_ent 
-                               else
-                                       which = peer;
-                               if (monitorfilename)
--                                      ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1 );
-+                                      ast_monitor_start(which, qe->parent->monfmt, monitorfilename, NULL, NULL, 1 );
-                               else if (qe->chan->cdr)
--                                      ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, 1 );
-+                                      ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, NULL, NULL, 1 );
-                               else {
-                                       /* Last ditch effort -- no CDR, make up something */
-                                       snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random());
--                                      ast_monitor_start(which, qe->parent->monfmt, tmpid, 1 );
-+                                      ast_monitor_start(which, qe->parent->monfmt, tmpid, NULL, NULL, 1 );
-                               }
-                               if (qe->parent->monjoin)
-                                       ast_monitor_setjoinfiles(which, 1);
---- a/channels/chan_agent.c
-+++ b/channels/chan_agent.c
-@@ -416,7 +416,7 @@ static int __agent_start_monitoring(stru
-               if ((pointer = strchr(filename, '.')))
-                       *pointer = '-';
-               snprintf(tmp, sizeof(tmp), "%s%s", savecallsin, filename);
--              ast_monitor_start(ast, recordformat, tmp, needlock);
-+              ast_monitor_start(ast, recordformat, tmp, NULL, NULL, needlock);
-               ast_monitor_setjoinfiles(ast, 1);
-               snprintf(tmp2, sizeof(tmp2), "%s%s.%s", urlprefix, filename, recordformatext);
- #if 0
---- a/include/asterisk/devicestate.h
-+++ b/include/asterisk/devicestate.h
-@@ -47,7 +47,7 @@ extern "C" {
- #define AST_DEVICE_ONHOLD     8
- /*! \brief Devicestate watcher call back */
--typedef int (*ast_devstate_cb_type)(const char *dev, int state, void *data);
-+typedef int (*ast_devstate_cb_type)(const char *dev, int state, void *data, char *cid_num, char *cid_name);
- /*!  \brief Devicestate provider call back */
- typedef int (*ast_devstate_prov_cb_type)(const char *data);
-@@ -92,7 +92,7 @@ int ast_device_state_changed(const char 
-  * callbacks for the changed extensions
-  * Returns 0 on success, -1 on failure
-  */
--int ast_device_state_changed_literal(const char *device);
-+int ast_device_state_changed_literal(const char *device, const char *cid_num, const char *cid_name);
- /*! \brief Registers a device state change callback 
-  * \param callback Callback
---- a/main/devicestate.c
-+++ b/main/devicestate.c
-@@ -78,6 +78,8 @@ static AST_LIST_HEAD_STATIC(devstate_cbs
- struct state_change {
-       AST_LIST_ENTRY(state_change) list;
-+      char cid_num[AST_MAX_EXTENSION];
-+      char cid_name[AST_MAX_EXTENSION];
-       char device[1];
+ struct zt_pri {
+       pthread_t master;                                               /*!< Thread of master */
+       ast_mutex_t lock;                                               /*!< Mutex */
+@@ -310,6 +317,8 @@ struct zt_pri {
+       int nsf;                                                        /*!< Network-Specific Facilities */
+       int dialplan;                                                   /*!< Dialing plan */
+       int localdialplan;                                              /*!< Local dialing plan */
++      char nocid[AST_MAX_EXTENSION];                                  /*!< CallerID string to use if none provided */
++      char withheldcid[AST_MAX_EXTENSION];                            /*!< CallerID string to use if CallerID is withheld */
+       char internationalprefix[10];                                   /*!< country access code ('00' for european dialplans) */
+       char nationalprefix[10];                                        /*!< area access code ('0' for european dialplans) */
+       char localprefix[20];                                           /*!< area access code + area code ('0'+area code for european dialplans) */
+@@ -321,6 +330,7 @@ struct zt_pri {
+       int prilogicalspan;                                             /*!< Logical span number within trunk group */
+       int numchans;                                                   /*!< Num of channels we represent */
+       int overlapdial;                                                /*!< In overlap dialing mode */
++      int usercid;
+       int facilityenable;                                             /*!< Enable facility IEs */
+       struct pri *dchans[NUM_DCHANS];                                 /*!< Actual d-channels */
+       int dchanavail[NUM_DCHANS];                                     /*!< Whether each channel is available */
+@@ -336,6 +346,8 @@ struct zt_pri {
+       struct zt_pvt *pvts[MAX_CHANNELS];                              /*!< Member channel pvt structs */
+       struct zt_pvt *crvs;                                            /*!< Member CRV structs */
+       struct zt_pvt *crvend;                                          /*!< Pointer to end of CRV structs */
++      struct zt_suspended_call *suspended_calls; /* Calls parked with SUSPEND messages */
++      int debugfd;
  };
  
-@@ -277,7 +279,7 @@ void ast_devstate_del(ast_devstate_cb_ty
- /*! \brief Notify callback watchers of change, and notify PBX core for hint updates
-       Normally executed within a separate thread
- */
--static void do_state_change(const char *device)
-+static void do_state_change(const char *device, char *cid_num, char *cid_name)
- {
-       int state;
-       struct devstate_cb *devcb;
-@@ -288,13 +290,13 @@ static void do_state_change(const char *
  
-       AST_LIST_LOCK(&devstate_cbs);
-       AST_LIST_TRAVERSE(&devstate_cbs, devcb, list)
--              devcb->callback(device, state, devcb->data);
-+              devcb->callback(device, state, devcb->data, cid_num, cid_name);
-       AST_LIST_UNLOCK(&devstate_cbs);
--      ast_hint_state_changed(device);
-+      ast_hint_state_changed(device, cid_num, cid_name);
- }
--static int __ast_device_state_changed_literal(char *buf)
-+static int __ast_device_state_changed_literal(char *buf, char *cid_num, char *cid_name)
- {
-       char *device;
-       struct state_change *change;
-@@ -312,10 +314,16 @@ static int __ast_device_state_changed_li
-       if (change_thread == AST_PTHREADT_NULL || !(change = ast_calloc(1, sizeof(*change) + strlen(device)))) {
-               /* we could not allocate a change struct, or */
-               /* there is no background thread, so process the change now */
--              do_state_change(device);
-+              do_state_change(device, cid_num, cid_name);
-       } else {
-               /* queue the change */
-               strcpy(change->device, device);
-+              if (cid_num && (!ast_strlen_zero(cid_num))) {
-+                  strncpy(change->cid_num, cid_num, sizeof(change->cid_num) - 1);
-+              }
-+              if (cid_name && (!ast_strlen_zero(cid_name))) {
-+                  strncpy(change->cid_name, cid_name, sizeof(change->cid_name) - 1);
-+              }
-               AST_LIST_LOCK(&state_changes);
-               AST_LIST_INSERT_TAIL(&state_changes, change, list);
-               if (AST_LIST_FIRST(&state_changes) == change)
-@@ -327,11 +335,17 @@ static int __ast_device_state_changed_li
-       return 1;
- }
+@@ -453,6 +465,8 @@ static struct zt_pvt {
+       unsigned int echocanbridged:1;
+       unsigned int echocanon:1;
+       unsigned int faxhandled:1;                      /*!< Has a fax tone already been handled? */
++                                                      /*!< KPJ: i will abuse this flag to implement a zapata option for dialing out
++                                                          on a zap channel with EC to be off no matter what happens. */
+       unsigned int firstradio:1;
+       unsigned int hanguponpolarityswitch:1;
+       unsigned int hardwaredtmf:1;
+@@ -467,7 +481,8 @@ static struct zt_pvt {
+       unsigned int overlapdial:1;
+       unsigned int permcallwaiting:1;
+       unsigned int permhidecallerid:1;                /*!< Whether to hide our outgoing caller ID or not */
+-      unsigned int priindication_oob:1;
++      unsigned int priindication_oob:2;
++      unsigned int pritransfer:2;
+       unsigned int priexclusive:1;
+       unsigned int pulse:1;
+       unsigned int pulsedial:1;                       /*!< whether a pulse dial phone is detected */
+@@ -504,6 +519,7 @@ static struct zt_pvt {
+ #endif
+       char cid_num[AST_MAX_EXTENSION];
+       int cid_ton;                                    /*!< Type Of Number (TON) */
++      int cid_pres;                                   /*!< Calling Presentation */
+       char cid_name[AST_MAX_EXTENSION];
+       char lastcid_num[AST_MAX_EXTENSION];
+       char lastcid_name[AST_MAX_EXTENSION];
+@@ -569,6 +585,8 @@ static struct zt_pvt {
+       struct zt_pvt *bearer;
+       struct zt_pvt *realcall;
+       q931_call *call;
++      int tei;                                        /* channel in use by this tei */
++      q931_call *holdedcall;
+       int prioffset;
+       int logicalspan;
+ #endif        
+@@ -614,11 +632,14 @@ static struct zt_chan_conf zt_chan_conf_
+                       .minunused = 2,
+                       .idleext = "",
+                       .idledial = "",
++                      .nocid = "No CID available",
++                      .withheldcid = "CID withheld",
+                       .internationalprefix = "",
+                       .nationalprefix = "",
+                       .localprefix = "",
+                       .privateprefix = "",
+                       .unknownprefix = "",
++                      .usercid = 0,
  
--int ast_device_state_changed_literal(const char *dev)
-+int ast_device_state_changed_literal(const char *dev, const char *cid_num, const char *cid_name)
- {
-       char *buf;
-+      char *buf2 = NULL;
-+      char *buf3 = NULL;
-       buf = ast_strdupa(dev);
--      return __ast_device_state_changed_literal(buf);
-+      if (cid_num)
-+          buf2 = ast_strdupa(cid_num);
-+      if (cid_name)
-+          buf3 = ast_strdupa(cid_name);
-+      return __ast_device_state_changed_literal(buf, buf2, buf3);
- }
+                       .resetinterval = 3600
+               },
+@@ -630,6 +651,8 @@ static struct zt_chan_conf zt_chan_conf_
+                       .mohinterpret = "default",
+                       .mohsuggest = "",
+                       .transfertobusy = 1,
++                      .priindication_oob = 0,
++                      .pritransfer = 0,
  
- /*! \brief Accept change notification, add it to change queue */
-@@ -343,7 +357,7 @@ int ast_device_state_changed(const char 
-       va_start(ap, fmt);
      vsnprintf(buf, sizeof(buf), fmt, ap);
      va_end(ap);
--      return __ast_device_state_changed_literal(buf);
-+      return __ast_device_state_changed_literal(buf, NULL, NULL);
- }
+                       .cid_signalling = CID_SIG_BELL,
+                       .cid_start = CID_START_RING,
+@@ -684,6 +707,8 @@ static int zt_indicate(struct ast_channe
static int zt_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
static int zt_setoption(struct ast_channel *chan, int option, void *data, int datalen);
+ static int zt_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len); 
++static void enable_dtmf_detect(struct zt_pvt *p);
++static void disable_dtmf_detect(struct zt_pvt *p);
  
- /*! \brief Go through the dev state change queue and update changes in the dev state thread */
-@@ -358,7 +372,7 @@ static void *do_devstate_changes(void *d
-               if (cur) {
-                       /* we got an entry, so unlock the list while we process it */
-                       AST_LIST_UNLOCK(&state_changes);
--                      do_state_change(cur->device);
-+                      do_state_change(cur->device, cur->cid_num, cur->cid_name);
-                       free(cur);
-                       AST_LIST_LOCK(&state_changes);
-               } else {
---- a/include/asterisk/channel.h
-+++ b/include/asterisk/channel.h
-@@ -590,8 +590,13 @@ int ast_channel_datastore_remove(struct 
- /*! \brief Find a datastore on a channel */
- struct ast_datastore *ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, char *uid);
+ static const struct ast_channel_tech zap_tech = {
+       .type = "Zap",
+@@ -715,6 +740,13 @@ static const struct ast_channel_tech zap
+ struct zt_pvt *round_robin[32];
  
-+extern ast_mutex_t uniquelock;                        
-+
-+/*! \brief Change the state of a channel and the callerid of the calling channel*/
-+int ast_setstate_and_cid(struct ast_channel *chan, enum ast_channel_state state, char *cid_num, char *cid_name);
+ #ifdef HAVE_PRI
++struct app_tmp {
++      char app[256];
++      char data[256];
++      struct ast_channel *chan;
++      pthread_t t;
++};
 +
- /*! \brief Change the state of a channel */
--int ast_setstate(struct ast_channel *chan, enum ast_channel_state);
-+int ast_setstate(struct ast_channel *chan, enum ast_channel_state state);
- /*! \brief Create a channel structure 
-     \return Returns NULL on failure to allocate.
---- a/main/channel.c
-+++ b/main/channel.c
-@@ -1277,7 +1277,7 @@ void ast_channel_free(struct ast_channel
-       free(chan);
-       AST_LIST_UNLOCK(&channels);
--      ast_device_state_changed_literal(name);
-+      ast_device_state_changed_literal(name, NULL, NULL);
- }
+ static inline int pri_grab(struct zt_pvt *pvt, struct zt_pri *pri)
+ {
+       int res;
+@@ -1417,12 +1449,16 @@ static void zt_enable_ec(struct zt_pvt *
+       int res;
+       if (!p)
+               return;
++      if (p->faxhandled)  {
++              ast_log(LOG_DEBUG, "Not enabling echo cancellation on a fax/modem call\n");
++              return;
++      }
+       if (p->echocanon) {
+               ast_log(LOG_DEBUG, "Echo cancellation already on\n");
+               return;
+       }
+       if (p->digital) {
+-              ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
++              ast_log(LOG_DEBUG, "Echo cancellation does not make any sense on digital connections!\n");
+               return;
+       }
+       if (p->echocancel) {
+@@ -1449,7 +1485,7 @@ static void zt_train_ec(struct zt_pvt *p
+ {
+       int x;
+       int res;
+-      if (p && p->echocancel && p->echotraining) {
++      if (p && p->echocancel && p->echotraining && (!p->digital) && (!p->faxhandled)) {
+               x = p->echotraining;
+               res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOTRAIN, &x);
+               if (res)
+@@ -1810,7 +1846,12 @@ static int zt_call(struct ast_channel *a
+               ast_log(LOG_WARNING, "Unable to flush input on channel %d\n", p->channel);
+       p->outgoing = 1;
  
- struct ast_datastore *ast_channel_datastore_alloc(const struct ast_datastore_info *info, char *uid)
-@@ -3941,7 +3941,7 @@ void ast_set_callerid(struct ast_channel
-       ast_channel_unlock(chan);
- }
+-      set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
++      if (IS_DIGITAL(ast->transfercapability)) {
++          set_actual_gain(p->subs[SUB_REAL].zfd, 0, 0, 0, p->law);
++      } else {
++          set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
++      }
++
  
--int ast_setstate(struct ast_channel *chan, enum ast_channel_state state)
-+int ast_setstate_and_cid(struct ast_channel *chan, enum ast_channel_state state, char *cid_num, char *cid_name)
- {
-       int oldstate = chan->_state;
+       mysig = p->sig;
+       if (p->outsigmod > -1)
+@@ -2041,6 +2082,7 @@ static int zt_call(struct ast_channel *a
+       case SIG_PRI:
+               /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
+               p->dialdest[0] = '\0';
++              disable_dtmf_detect(p);
+               break;
+       default:
+               ast_log(LOG_DEBUG, "not yet implemented\n");
+@@ -2061,6 +2103,12 @@ static int zt_call(struct ast_channel *a
+               const char *rr_str;
+               int redirect_reason;
  
-@@ -3949,7 +3949,7 @@ int ast_setstate(struct ast_channel *cha
-               return 0;
++              if ((p->pri->nodetype == BRI_NETWORK_PTMP) || (p->pri->nodetype == BRI_NETWORK)) {
++                  // pass NO audio when ringing an isdn phone
++                  p->dialing = 1;
++                  // maybe we could allow passing audio when calling a p2p PBX, but well... ;-)
++              }
++
+               c = strchr(dest, '/');
+               if (c)
+                       c++;
+@@ -2083,6 +2131,7 @@ static int zt_call(struct ast_channel *a
+                       ast_mutex_unlock(&p->lock);
+                       return -1;
+               }
++              strncpy(p->dnid, (c + p->stripmsd), sizeof(p->dnid)-1);
+               if (mysig != SIG_FXSKS) {
+                       p->dop.op = ZT_DIAL_OP_REPLACE;
+                       s = strchr(c + p->stripmsd, 'w');
+@@ -2106,6 +2155,8 @@ static int zt_call(struct ast_channel *a
+                       pri_rel(p->pri);
+                       ast_mutex_unlock(&p->lock);
+                       return -1;
++              } else {
++              //      ast_log(LOG_NOTICE, "call %d\n", p->call);
+               }
+               if (!(sr = pri_sr_new())) {
+                       ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
+@@ -2135,7 +2186,7 @@ static int zt_call(struct ast_channel *a
+               pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
+               pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 
+                                       (p->digital ? -1 : 
+-                                              ((p->law == ZT_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
++                                              ((p->law == ZT_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)), ast->lowlayercompat);
+               if (p->pri->facilityenable)
+                       pri_facility_enable(p->pri->pri);
  
-       chan->_state = state;
--      ast_device_state_changed_literal(chan->name);
-+      ast_device_state_changed_literal(chan->name, cid_num, cid_name);
-       /* setstate used to conditionally report Newchannel; this is no more */
-       manager_event(EVENT_FLAG_CALL,
-                     "Newstate",
-@@ -3966,6 +3966,11 @@ int ast_setstate(struct ast_channel *cha
-       return 0;
+@@ -2399,8 +2450,10 @@ static int pri_find_dchan(struct zt_pri 
+       }
+       if (newslot < 0) {
+               newslot = 0;
+-              ast_log(LOG_WARNING, "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
++              if (pri->nodetype != BRI_CPE_PTMP) {
++                  ast_log(LOG_WARNING, "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
+                       pri->dchannels[newslot]);
++              }
+       }
+       if (old && (oldslot != newslot))
+               ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
+@@ -2410,6 +2463,16 @@ static int pri_find_dchan(struct zt_pri 
  }
+ #endif
  
-+int ast_setstate(struct ast_channel *chan, enum ast_channel_state state)
++static int zt_setlaw(int zfd, int law)
 +{
-+    return ast_setstate_and_cid(chan, state, NULL, NULL);
++      int res;
++      res = ioctl(zfd, ZT_SETLAW, &law);
++      if (res)
++              return res;
++      return 0;
 +}
 +
- /*! \brief Find bridged channel */
- struct ast_channel *ast_bridged_channel(struct ast_channel *chan)
++
+ static int zt_hangup(struct ast_channel *ast)
  {
---- a/include/asterisk/pbx.h
-+++ b/include/asterisk/pbx.h
-@@ -63,7 +63,7 @@ struct ast_ignorepat;
- struct ast_sw;
- /*! \brief Typedef for devicestate and hint callbacks */
--typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data);
-+typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data, char *cid_num, char *cid_name);
- /*! \brief Data structure associated with a custom dialplan function */
- struct ast_custom_function {
-@@ -875,7 +875,7 @@ int ast_func_read(struct ast_channel *ch
-  */
- int ast_func_write(struct ast_channel *chan, char *function, const char *value);
--void ast_hint_state_changed(const char *device);
-+void ast_hint_state_changed(const char *device, char *cid_num, char *cid_name);
- #if defined(__cplusplus) || defined(c_plusplus)
- }
---- a/main/pbx.c
-+++ b/main/pbx.c
-@@ -2011,7 +2011,7 @@ int ast_extension_state(struct ast_chann
-       return ast_extension_state2(e);                 /* Check all devices in the hint */
- }
--void ast_hint_state_changed(const char *device)
-+void ast_hint_state_changed(const char *device, char *cid_num, char *cid_name)
- {
-       struct ast_hint *hint;
-@@ -2042,11 +2042,11 @@ void ast_hint_state_changed(const char *
-               /* For general callbacks */
-               for (cblist = statecbs; cblist; cblist = cblist->next)
--                      cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
-+                      cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data, cid_num, cid_name);
-               /* For extension callbacks */
-               for (cblist = hint->callbacks; cblist; cblist = cblist->next)
--                      cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
-+                      cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data, cid_num, cid_name);
-               hint->laststate = state;        /* record we saw the change */
+       int res;
+@@ -2457,8 +2520,7 @@ static int zt_hangup(struct ast_channel 
+       if (option_debug)
+               ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
+               p->channel, index, p->subs[SUB_REAL].zfd, p->subs[SUB_CALLWAIT].zfd, p->subs[SUB_THREEWAY].zfd);
+-      p->ignoredtmf = 0;
+-      
++
+       if (index > -1) {
+               /* Real channel, do some fixup */
+               p->subs[index].owner = NULL;
+@@ -2560,6 +2622,7 @@ static int zt_hangup(struct ast_channel 
        }
-@@ -2241,7 +2241,7 @@ static int ast_remove_hint(struct ast_ex
-                               /* Notify with -1 and remove all callbacks */
-                               cbprev = cblist;
-                               cblist = cblist->next;
--                              cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data);
-+                              cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data, NULL, NULL);
-                               free(cbprev);
-                       }
-                       hint->callbacks = NULL;
-@@ -4008,7 +4008,7 @@ void ast_merge_contexts_and_delete(struc
-                       while (thiscb) {
-                               prevcb = thiscb;
-                               thiscb = thiscb->next;
--                              prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data);
-+                              prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data, NULL, NULL);
-                               free(prevcb);
-                       }
-               } else {
---- a/channels/chan_sip.c
-+++ b/channels/chan_sip.c
-@@ -1338,7 +1338,7 @@ static void ast_quiet_chan(struct ast_ch
- static int attempt_transfer(struct sip_dual *transferer, struct sip_dual *target);
- /*--- Device monitoring and Device/extension state handling */
--static int cb_extensionstate(char *context, char* exten, int state, void *data);
-+static int cb_extensionstate(char *context, char* exten, int state, void *data, char *cid_num, char *cid_name);
- static int sip_devicestate(void *data);
- static int sip_poke_noanswer(const void *data);
- static int sip_poke_peer(struct sip_peer *peer);
-@@ -8459,7 +8459,7 @@ static void sip_peer_hold(struct sip_pvt
- /*! \brief Callback for the devicestate notification (SUBSCRIBE) support subsystem
- \note If you add an "hint" priority to the extension in the dial plan,
-       you will get notifications on device state changes */
--static int cb_extensionstate(char *context, char* exten, int state, void *data)
-+static int cb_extensionstate(char *context, char* exten, int state, void *data, char *cid_num, char *cid_name)
- {
-       struct sip_pvt *p = data;
  
---- a/apps/app_queue.c
-+++ b/apps/app_queue.c
-@@ -690,7 +690,7 @@ static void *device_state_thread(void *d
-       return NULL;
- }
+       if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
++              int outgoing = p->outgoing;
+               p->owner = NULL;
+               p->ringt = 0;
+               p->distinctivering = 0;
+@@ -2602,7 +2665,7 @@ static int zt_hangup(struct ast_channel 
+                                               pri_call_set_useruser(p->call, useruser);
+ #endif
  
--static int statechange_queue(const char *dev, int state, void *ign)
-+static int statechange_queue(const char *dev, int state, void *ign, char *cid_num, char *cid_name)
+-                                              pri_hangup(p->pri->pri, p->call, -1);
++                                              pri_hangup(p->pri->pri, p->call, -1, -1);
+                                               p->call = NULL;
+                                               if (p->bearer) 
+                                                       p->bearer->call = NULL;
+@@ -2622,7 +2685,28 @@ static int zt_hangup(struct ast_channel 
+                                                       if (atoi(cause))
+                                                               icause = atoi(cause);
+                                               }
+-                                              pri_hangup(p->pri->pri, p->call, icause);
++
++                                              pri_hangup(p->pri->pri, p->call, icause, -1);
++
++                                              /* if we send a rel9999ease complete we wont ge no hangup event, so clear the call here */
++                                              if (icause == 34 || icause == 44 || icause == 82 || icause == 1 || icause == 81 || icause == 17) {
++                                                  if ((ast->_state == AST_STATE_RING) || (ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING) || (ast->_state == AST_STATE_RESERVED)) {
++                                                      p->call = NULL;
++                                                  } else {
++                                                      ast_log(LOG_ERROR, "What is wrong with you? You cannot use cause %d number when in state %d!\n", icause, ast->_state);
++                                                      icause = 16; /* Note, in pri_hangup() libpri will already override the cause */
++                                                  }
++                                              }
++
++                                              if (p->pri->nodetype == BRI_NETWORK_PTMP) {
++                                                  if ((icause == 16 || icause == -1) && (ast->_state != AST_STATE_UP)) {
++                                                      if (outgoing) {
++                                                          p->call = NULL;
++                                                      }
++                                                  }
++                                              }
++
++
+                                       }
+                                       if (res < 0) 
+                                               ast_log(LOG_WARNING, "pri_disconnect failed\n");
+@@ -2806,10 +2890,14 @@ static int zt_answer(struct ast_channel 
+                       p->proceeding = 1;
+                       res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
+                       pri_rel(p->pri);
++                      /* stop ignoring inband dtmf */
++                      enable_dtmf_detect(p);
+               } else {
+                       ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
+                       res = -1;
+               }
++              /* the audio path is complete now, train the echo canceler */
++              zt_train_ec(p);
+               break;
+ #endif
+       case 0:
+@@ -3446,6 +3534,15 @@ static int zt_fixup(struct ast_channel *
  {
-       struct statechange *sc;
---- a/include/asterisk/manager.h
-+++ b/include/asterisk/manager.h
-@@ -55,6 +55,7 @@
- #define EVENT_FLAG_AGENT              (1 << 5) /* Ability to read/set agent info */
- #define EVENT_FLAG_USER                 (1 << 6) /* Ability to read/set user info */
- #define EVENT_FLAG_CONFIG             (1 << 7) /* Ability to modify configurations */
-+#define EVENT_FLAG_EXTENSIONSTATUS    (1 << 8) /* ExtensionStatus events */
+       struct zt_pvt *p = newchan->tech_pvt;
+       int x;
++      if (newchan && newchan->tech_pvt) {
++          p = newchan->tech_pvt;
++      }
++      if (!p) {
++          if (newchan) {
++              ast_log(LOG_ERROR, "channel %s has no tech_pvt structure\n", newchan->name);
++          }
++          return 0;
++      }
+       ast_mutex_lock(&p->lock);
+       ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
+       if (p->owner == oldchan) {
+@@ -3655,8 +3752,10 @@ static void zt_handle_dtmfup(struct ast_
+                                       pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
+                                       if (ast_async_goto(ast, target_context, "fax", 1))
+                                               ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
+-                              } else
++                              } else {
++                                  if (option_verbose > 2)
+                                       ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
++                              }
+                       } else if (option_debug)
+                               ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
+               } else if (option_debug)
+@@ -3815,7 +3914,7 @@ static struct ast_frame *zt_handle_event
+                               if (p->call) {
+                                       if (p->pri && p->pri->pri) {
+                                               if (!pri_grab(p, p->pri)) {
+-                                                      pri_hangup(p->pri->pri, p->call, -1);
++                                                      pri_hangup(p->pri->pri, p->call, -1, -1);
+                                                       pri_destroycall(p->pri->pri, p->call);
+                                                       p->call = NULL;
+                                                       pri_rel(p->pri);
+@@ -4886,7 +4985,7 @@ static struct ast_frame  *zt_read(struct
+               p->subs[index].f.data = NULL;
+               p->subs[index].f.datalen= 0;
+       }
+-      if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect  || p->callprogress) && !index) {
++      if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
+               /* Perform busy detection. etc on the zap line */
+               f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
+               if (f) {
+@@ -4898,8 +4997,9 @@ static struct ast_frame  *zt_read(struct
+                               }
+                       } else if (f->frametype == AST_FRAME_DTMF) {
+ #ifdef HAVE_PRI
+-                              if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
+-                                      /* Don't accept in-band DTMF when in overlap dial mode */
++                              if (p->sig==SIG_PRI && p->pri && p->pri->overlapdial && p->ignoredtmf) {
++                                      /* Don't accept in-band DTMF when in overlap dial mode
++                                         or when in non-overlap overlapdialing mode ... */
+                                       f->frametype = AST_FRAME_NULL;
+                                       f->subclass = 0;
+                               }
+@@ -4974,7 +5074,9 @@ static int zt_write(struct ast_channel *
+ #endif
+       /* Write a frame of (presumably voice) data */
+       if (frame->frametype != AST_FRAME_VOICE) {
+-              if (frame->frametype != AST_FRAME_IMAGE)
++              if (frame->frametype == AST_FRAME_TEXT) {
++                      ast_log(LOG_NOTICE, "text\n");
++              } else if (frame->frametype != AST_FRAME_IMAGE)
+                       ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
+               return 0;
+       }
+@@ -5042,7 +5144,7 @@ static int zt_indicate(struct ast_channe
+               switch (condition) {
+               case AST_CONTROL_BUSY:
+ #ifdef HAVE_PRI
+-                      if (p->priindication_oob && p->sig == SIG_PRI) {
++                      if ((p->priindication_oob == 1) && p->sig == SIG_PRI) {
+                               chan->hangupcause = AST_CAUSE_USER_BUSY;
+                               chan->_softhangup |= AST_SOFTHANGUP_DEV;
+                               res = 0;
+@@ -5124,7 +5226,7 @@ static int zt_indicate(struct ast_channe
+               case AST_CONTROL_CONGESTION:
+                       chan->hangupcause = AST_CAUSE_CONGESTION;
+ #ifdef HAVE_PRI
+-                      if (p->priindication_oob && p->sig == SIG_PRI) {
++                      if ((p->priindication_oob == 1) && p->sig == SIG_PRI) {
+                               chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
+                               chan->_softhangup |= AST_SOFTHANGUP_DEV;
+                               res = 0;
+@@ -5321,8 +5423,12 @@ static struct ast_channel *zt_new(struct
+       if (state == AST_STATE_RING)
+               tmp->rings = 1;
+       tmp->tech_pvt = i;
++#ifdef HAVE_PRI
++      if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS) || (i->sig == SIG_PRI)) {
++#else
+       if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
+-              /* Only FXO signalled stuff can be picked up */
++#endif
++              /* Only FXO signalled stuff can be picked up */ /* i dont think so, mr. ulaw! we alaws like to pick up BRIs/PRIs */
+               tmp->callgroup = i->callgroup;
+               tmp->pickupgroup = i->pickupgroup;
+       }
+@@ -5452,6 +5558,7 @@ static void *ss_thread(void *data)
+       int len = 0;
+       int res;
+       int index;
++      int network;
  
- /* Export manager structures */
- #define AST_MAX_MANHEADERS 128
---- a/main/manager.c
-+++ b/main/manager.c
-@@ -129,6 +129,7 @@ static struct permalias {
-       { EVENT_FLAG_AGENT, "agent" },
-       { EVENT_FLAG_USER, "user" },
-       { EVENT_FLAG_CONFIG, "config" },
-+      { EVENT_FLAG_EXTENSIONSTATUS, "extensionstatus" },
-       { -1, "all" },
-       { 0, "none" },
- };
-@@ -2538,10 +2539,12 @@ int ast_manager_unregister(char *action)
-       return 0;
+       /* in the bizarre case where the channel has become a zombie before we
+          even get started here, abort safely
+@@ -5480,10 +5587,17 @@ static void *ss_thread(void *data)
+               len = strlen(exten);
+               res = 0;
+               while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
+-                      if (len && !ast_ignore_pattern(chan->context, exten))
++                      if (len && !ast_ignore_pattern(chan->context, exten)) {
+                               tone_zone_play_tone(p->subs[index].zfd, -1);
+-                      else
+-                              tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
++                      } else {
++                              network = p->pri->nodetype == PRI_NETWORK || p->pri->nodetype == BRI_NETWORK || p->pri->nodetype == BRI_NETWORK_PTMP;
++                              if (network) {
++                                  tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
++                              } else {
++                                  /* cpe be quiet */
++                                  tone_zone_play_tone(p->subs[index].zfd, -1);
++                              }
++                      }
+                       if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
+                               timeout = matchdigittimeout;
+                       else
+@@ -6697,9 +6811,20 @@ static int handle_init_event(struct zt_p
+       case ZT_EVENT_NOALARM:
+               i->inalarm = 0;
+               if (!i->unknown_alarm) {
++#ifdef HAVE_PRI
++                  if (i->pri) {
++                      if ((i->pri->nodetype == BRI_CPE_PTMP) || (i->pri->nodetype == BRI_CPE)) {
++                          /* dont annoy BRI TE mode users with layer2layer alarms */
++                      } else {
++#endif
+                       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
+                       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
+                               "Channel: %d\r\n", i->channel);
++#ifdef HAVE_PRI
++                      }
++                  }
++#endif
++
+               } else {
+                       i->unknown_alarm = 0;
+               }
+@@ -6708,7 +6833,13 @@ static int handle_init_event(struct zt_p
+               i->inalarm = 1;
+               res = get_alarms(i);
+               do {
+-                      const char *alarm_str = alarm2str(res);
++#ifdef HAVE_PRI
++                  if (i->pri) {
++                      if ((i->pri->nodetype == BRI_CPE_PTMP) || (i->pri->nodetype == BRI_CPE)) {
++                          /* dont annoy BRI TE mode users with layer2layer alarms */
++                      } else {
++#endif
++                          const char *alarm_str = alarm2str(res);
+                       /* hack alert!  Zaptel 1.4 now exposes FXO battery as an alarm, but asterisk 1.4
+                        * doesn't know what to do with it.  Don't confuse users with log messages. */
+@@ -6724,6 +6855,10 @@ static int handle_init_event(struct zt_p
+                               "Alarm: %s\r\n"
+                               "Channel: %d\r\n",
+                               alarm_str, i->channel);
++#ifdef HAVE_PRI
++                      }
++                  }
++#endif
+               } while (0);
+               /* fall thru intentionally */
+       case ZT_EVENT_ONHOOK:
+@@ -6768,8 +6903,10 @@ static int handle_init_event(struct zt_p
+                       zt_set_hook(i->subs[SUB_REAL].zfd, ZT_ONHOOK);
+                       break;
+               case SIG_PRI:
+-                      zt_disable_ec(i);
+-                      res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
++                      if (event != ZT_EVENT_ALARM) {
++                          zt_disable_ec(i);
++                          res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
++                      }
+                       break;
+               default:
+                       ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
+@@ -7062,6 +7199,8 @@ static int pri_resolve_span(int *span, i
+               } else {
+                       if (si->totalchans == 31) { /* if it's an E1 */
+                               pris[*span].dchannels[0] = 16 + offset;
++                      } else if (si->totalchans == 3) { /* if it's an S0 ZAPBRI */
++                              pris[*span].dchannels[0] = 3 + offset;
+                       } else {
+                               pris[*span].dchannels[0] = 24 + offset;
+                       }
+@@ -7314,6 +7453,11 @@ static struct zt_pvt *mkintf(int channel
+                                                       destroy_zt_pvt(&tmp);
+                                                       return NULL;
+                                               }
++                                              if ((pris[span].localdialplan) && (pris[span].localdialplan != conf->pri.localdialplan)) {
++                                                      ast_log(LOG_ERROR, "Span %d is already a %s local dialing plan\n", span + 1, dialplan2str(pris[span].localdialplan));
++                                                      destroy_zt_pvt(&tmp);
++                                                      return NULL;
++                                              }
+                                               if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
+                                                       ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
+                                                       destroy_zt_pvt(&tmp);
+@@ -7331,6 +7475,11 @@ static struct zt_pvt *mkintf(int channel
+                                                       return NULL;
+                                               }
+                                               pris[span].nodetype = conf->pri.nodetype;
++
++                                              if (conf->pri.nodetype == BRI_NETWORK_PTMP) {
++                                                  pris[span].dchanavail[0] =  DCHAN_AVAILABLE;
++                                                  pri_find_dchan(&pris[span]);
++                                              }
+                                               pris[span].switchtype = myswitchtype;
+                                               pris[span].nsf = conf->pri.nsf;
+                                               pris[span].dialplan = conf->pri.dialplan;
+@@ -7339,9 +7488,13 @@ static struct zt_pvt *mkintf(int channel
+                                               pris[span].minunused = conf->pri.minunused;
+                                               pris[span].minidle = conf->pri.minidle;
+                                               pris[span].overlapdial = conf->pri.overlapdial;
++                                              pris[span].usercid = conf->pri.usercid;
++                                              pris[span].suspended_calls = NULL;
+                                               pris[span].facilityenable = conf->pri.facilityenable;
+                                               ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
+                                               ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
++                                              ast_copy_string(pris[span].nocid, conf->pri.nocid, sizeof(pris[span].nocid));
++                                              ast_copy_string(pris[span].withheldcid, conf->pri.withheldcid, sizeof(pris[span].withheldcid));
+                                               ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
+                                               ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
+                                               ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
+@@ -7483,6 +7636,7 @@ static struct zt_pvt *mkintf(int channel
+               tmp->restrictcid = conf->chan.restrictcid;
+               tmp->use_callingpres = conf->chan.use_callingpres;
+               tmp->priindication_oob = conf->chan.priindication_oob;
++              tmp->pritransfer = conf->chan.pritransfer;
+               tmp->priexclusive = conf->chan.priexclusive;
+               if (tmp->usedistinctiveringdetection) {
+                       if (!tmp->use_callerid) {
+@@ -7765,7 +7919,7 @@ static int pri_find_empty_chan(struct zt
+                       break;
+               if (!backwards && (x >= pri->numchans))
+                       break;
+-              if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
++              if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner && !pri->pvts[x]->call) {
+                       ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n", 
+                               pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
+                       return x;
+@@ -7961,6 +8115,11 @@ static struct ast_channel *zt_request(co
+                                       p->digital = 1;
+                                       if (tmp)
+                                               tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
++                              } else if (opt == 'm') {
++                                      /* If this is a modem/fax call, pretend to have the fax handled and dont do EC */
++                                      p->faxhandled = 1;
++                                      if (tmp)
++                                          tmp->transfercapability = AST_TRANS_CAP_3_1K_AUDIO;
+                               } else {
+                                       ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
+                               }
+@@ -7994,13 +8153,14 @@ next:
+                               *cause = AST_CAUSE_BUSY;
+               } else if (groupmatched) {
+                       *cause = AST_CAUSE_CONGESTION;
++              } else {
++                      *cause = AST_CAUSE_CONGESTION;
+               }
+       }
+               
+       return tmp;
  }
  
--static int manager_state_cb(char *context, char *exten, int state, void *data)
-+static int manager_state_cb(char *context, char *exten, int state, void *data, char *cid_num, char *cid_name)
+-
+ #ifdef HAVE_PRI
+ static struct zt_pvt *pri_find_crv(struct zt_pri *pri, int crv)
  {
-+      char hint[256] = "";
-+      ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten);
-       /* Notify managers of change */
--      manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nStatus: %d\r\n", exten, context, state);
-+      manager_event(EVENT_FLAG_EXTENSIONSTATUS, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nStatus: %d\r\nCallerID: \"%s\" <%s>\r\nHint: %s\r\n", exten, context, state, cid_num, cid_name, hint);
-       return 0;
+@@ -8045,6 +8205,7 @@ static int pri_find_principle(struct zt_
+ static int pri_fixup_principle(struct zt_pri *pri, int principle, q931_call *c)
+ {
+       int x;
++      int res = 0;
+       struct zt_pvt *crv;
+       if (!c) {
+               if (principle < 0)
+@@ -8075,6 +8236,7 @@ static int pri_fixup_principle(struct zt
+                               }
+                               /* Fix it all up now */
+                               new->owner = old->owner;
++                              new->outgoing = old->outgoing;
+                               old->owner = NULL;
+                               if (new->owner) {
+                                       ast_string_field_build(new->owner, name, 
+@@ -8094,6 +8256,34 @@ static int pri_fixup_principle(struct zt
+                               new->dsp_features = old->dsp_features;
+                               old->dsp = NULL;
+                               old->dsp_features = 0;
++
++                              /* Copy faxhandled/digial, alreadyhungup */
++                              new->faxhandled = old->faxhandled;
++                              new->digital = old->digital;
++                              new->alreadyhungup = old->alreadyhungup;
++
++                              /* Copy law, gains, etc */
++                              new->law = old->law;
++                              if (ioctl(new->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &new->law) == -1)
++                                  ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", new->channel, new->law);
++                              res = zt_setlaw(new->subs[SUB_REAL].zfd, new->law);
++                              if (res < 0)
++                                  ast_log(LOG_WARNING, "Unable to set law on channel %d\n", new->channel);
++                              if (!new->digital) {
++                                  res = set_actual_gain(new->subs[SUB_REAL].zfd, 0, new->rxgain, new->txgain, new->law);
++                              } else {
++                                  res = set_actual_gain(new->subs[SUB_REAL].zfd, 0, 0, 0, new->law);
++                              }
++                              if (res < 0)
++                                  ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", new->channel);
++
++                              /* Shutdown old channel */
++                              zt_confmute(old, 0);
++                              update_conf(old);
++                              reset_conf(old);
++                              restore_gains(old);
++                              zt_disable_ec(old);
++                              zt_setlinear(old->subs[SUB_REAL].zfd, 0);
+                       }
+                       return principle;
+               }
+@@ -8122,7 +8312,9 @@ static int pri_fixup_principle(struct zt
+               }
+               crv = crv->next;
+       }
+-      ast_log(LOG_WARNING, "Call specified, but not found?\n");
++      if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
++          ast_log(LOG_WARNING, "Call specified, but not found?\n");
++      }
+       return -1;
  }
  
---- a/apps/app_devstate.c
-+++ b/apps/app_devstate.c
-@@ -50,7 +50,7 @@ static struct ast_cli_entry  cli_dev_sta
- static int devstate_cli(int fd, int argc, char *argv[])
+@@ -8181,86 +8373,21 @@ static void *do_idle_thread(void *vchan)
+ #ifndef PRI_RESTART
+ #error "Upgrade your libpri"
+ #endif
+-static void zt_pri_message(struct pri *pri, char *s)
++static void zt_pri_message(char *s, int span)
  {
-     char devName[128];
--    if (argc != 3)
-+    if ((argc != 3) && (argc != 4) && (argc != 5))
-         return RESULT_SHOWUSAGE;
+-      int x, y;
+-      int dchan = -1, span = -1;
+-      int dchancount = 0;
+-
+-      if (pri) {
+-              for (x = 0; x < NUM_SPANS; x++) {
+-                      for (y = 0; y < NUM_DCHANS; y++) {
+-                              if (pris[x].dchans[y])
+-                                      dchancount++;
+-
+-                              if (pris[x].dchans[y] == pri)
+-                                      dchan = y;
+-                      }
+-                      if (dchan >= 0) {
+-                              span = x;
+-                              break;
+-                      }
+-                      dchancount = 0;
+-              }
+-              if ((dchan >= 0) && (span >= 0)) {
+-                      if (dchancount > 1)
+-                              ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
+-                      else
+-                              ast_verbose("%s", s);
+-              } else
+-                      ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
+-      } else
+-              ast_verbose("%s", s);
+-
+-      ast_mutex_lock(&pridebugfdlock);
+-
+-      if (pridebugfd >= 0)
+-              write(pridebugfd, s, strlen(s));
+-
+-      ast_mutex_unlock(&pridebugfdlock);
++      ast_verbose("%d %s", span, s);
+ }
  
-     if (ast_db_put("DEVSTATES", argv[1], argv[2]))
-@@ -58,7 +58,15 @@ static int devstate_cli(int fd, int argc
-         ast_log(LOG_DEBUG, "ast_db_put failed\n");
-     }
-     snprintf(devName, sizeof(devName), "DS/%s", argv[1]);
--    ast_device_state_changed_literal(devName);
-+    if (argc == 4) {
-+        ast_log(LOG_NOTICE, "devname %s cid %s\n", devName, argv[3]);
-+      ast_device_state_changed_literal(devName, argv[3], NULL);
-+    } else if (argc == 5) {
-+        ast_log(LOG_NOTICE, "devname %s cid %s cidname %s\n", devName, argv[3], argv[4]);
-+      ast_device_state_changed_literal(devName, argv[3], argv[4]);
-+    } else {
-+      ast_device_state_changed_literal(devName, NULL, NULL);
-+    }
-     return RESULT_SUCCESS;
+-static void zt_pri_error(struct pri *pri, char *s)
++static void zt_pri_error(char *s, int span)
+ {
+-      int x, y;
+-      int dchan = -1, span = -1;
+-      int dchancount = 0;
+-
+-      if (pri) {
+-              for (x = 0; x < NUM_SPANS; x++) {
+-                      for (y = 0; y < NUM_DCHANS; y++) {
+-                              if (pris[x].dchans[y])
+-                                      dchancount++;
+-
+-                              if (pris[x].dchans[y] == pri)
+-                                      dchan = y;
+-                      }
+-                      if (dchan >= 0) {
+-                              span = x;
+-                              break;
+-                      }
+-                      dchancount = 0;
+-              }
+-              if ((dchan >= 0) && (span >= 0)) {
+-                      if (dchancount > 1)
+-                              ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
+-                      else
+-                              ast_log(LOG_ERROR, "%s", s);
+-              } else
+-                      ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
+-      } else
+-              ast_log(LOG_ERROR, "%s", s);
+-
+-      ast_mutex_lock(&pridebugfdlock);
+-
+-      if (pridebugfd >= 0)
+-              write(pridebugfd, s, strlen(s));
+-
+-      ast_mutex_unlock(&pridebugfdlock);
++      ast_log(LOG_WARNING, "%d %s", span, s);
  }
  
-@@ -93,7 +101,7 @@ static int devstate_exec(struct ast_chan
-     }
-     snprintf(devName, sizeof(devName), "DS/%s", device);
--    ast_device_state_changed_literal(devName);
-+    ast_device_state_changed_literal(devName, NULL, NULL);
-     ast_module_user_remove(u);
-     return 0;
-@@ -150,6 +158,8 @@ static int action_devstate(struct manses
-         const char *devstate = astman_get_header(m, "Devstate");
-         const char *value = astman_get_header(m, "Value");
-       const char *id = astman_get_header(m,"ActionID");
-+        const char *cid_num = astman_get_header(m, "CallerID");
-+        const char *cid_name = astman_get_header(m, "CallerIDName");
-       char devName[128];
-       char idText[256] = "";
-@@ -166,7 +176,7 @@ static int action_devstate(struct manses
-         if (!ast_db_put("DEVSTATES", devstate, (char *)value)) {
-           snprintf(devName, sizeof(devName), "DS/%s", devstate);
--          ast_device_state_changed_literal(devName);
-+          ast_device_state_changed_literal(devName, cid_num, cid_name);
-           astman_append(s, "Response: Success\r\n%s\r\n", idText);
-       } else {
-           ast_log(LOG_DEBUG, "ast_db_put failed\n");
---- a/res/res_esel.c
-+++ b/res/res_esel.c
-@@ -51,6 +51,8 @@ typedef struct esel_extension_state {
-     char context[AST_MAX_EXTENSION];
-     char exten[AST_MAX_EXTENSION];
-     int state;
-+    char cid_num[AST_MAX_EXTENSION];
-+    char cid_name[AST_MAX_EXTENSION];
-     char devstate[AST_MAX_EXTENSION];
-     struct esel_extension_state *next;
-     struct esel_extension_state *prev;
-@@ -93,7 +95,7 @@ typedef struct esel_pvt {
- static struct esel_pvt *donkeys = NULL;
--static int esel_queue_extension_state(struct esel_queue *queue, char *context, char *exten, int state, void *data) {
-+static int esel_queue_extension_state(struct esel_queue *queue, char *context, char *exten, int state, void *data, char *cid_num, char *cid_name) {
-       struct esel_extension_state *exstate = NULL;
-       exstate = malloc(sizeof(struct esel_extension_state));
-@@ -115,6 +117,8 @@ static int esel_queue_extension_state(st
-       }
-       ast_copy_string(exstate->exten, exten, sizeof(exstate->exten));
-       ast_copy_string(exstate->context, context, sizeof(exstate->context));
-+      ast_copy_string(exstate->cid_num, cid_num, sizeof(exstate->cid_num));
-+      ast_copy_string(exstate->cid_name, cid_name, sizeof(exstate->cid_name));
-       exstate->state = state;
-       if (!queue->head) {
-               /* Empty queue */
-@@ -161,7 +165,7 @@ static void esel_export_to_remote(struct
-     char msg[1024];
-     int sent = 0;
-     memset(msg, 0x0, sizeof(msg));
--    snprintf(msg, sizeof(msg) - 1, "Action: Devstate\r\nDevstate: %s\r\nValue: %d\r\n\r\n", exstate->devstate, esel_state2devstate(exstate->state));
-+    snprintf(msg, sizeof(msg) - 1, "Action: Devstate\r\nDevstate: %s\r\nValue: %d\r\nCallerID: %s\r\nCallerIDName: %s\r\n\r\n", exstate->devstate, esel_state2devstate(exstate->state), exstate->cid_num, exstate->cid_name);
-     sent = send(esel->sockfd, msg, strlen(msg), 0);
-     if (sent == -1) {
-       esel->connected = 0;
-@@ -250,13 +254,13 @@ static void *do_esel_thread(void *data) 
-     return NULL;
- }
--static int esel_state_cb(char *context, char *exten, int state, void *data) {
-+static int esel_state_cb(char *context, char *exten, int state, void *data, char *cid_num, char *cid_name) {
-       struct esel_pvt *esel;
-       esel = donkeys;
-         ast_mutex_lock(&listlock);
-       while (esel) {
--          esel_queue_extension_state(&esel->queue, context, exten, state, data);
-+          esel_queue_extension_state(&esel->queue, context, exten, state, data, cid_num, cid_name);
-           esel = esel->next;
-       }
-         ast_mutex_unlock(&listlock);
-Use Asterisk's process ID when building the unique ID.
-
---- a/main/channel.c
-+++ b/main/channel.c
-@@ -808,10 +808,10 @@ struct ast_channel *ast_channel_alloc(in
-       tmp->fout = global_fout;
-       if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME)) {
--              ast_string_field_build(tmp, uniqueid, "%li.%d", (long) time(NULL), 
-+              ast_string_field_build(tmp, uniqueid, "%d-%li.%d", ast_mainpid, (long) time(NULL), 
-                       ast_atomic_fetchadd_int(&uniqueint, 1));
-       } else {
--              ast_string_field_build(tmp, uniqueid, "%s-%li.%d", ast_config_AST_SYSTEM_NAME, 
-+              ast_string_field_build(tmp, uniqueid, "%s-%d-%li.%d", ast_config_AST_SYSTEM_NAME, ast_mainpid,
-                       (long) time(NULL), ast_atomic_fetchadd_int(&uniqueint, 1));
-       }
-Add or convert channel operations so they can use the unique ID.
-
---- a/include/asterisk/channel.h
-+++ b/include/asterisk/channel.h
-@@ -659,6 +659,18 @@ void  ast_channel_free(struct ast_channe
-  */
- struct ast_channel *ast_request(const char *type, int format, void *data, int *status);
-+/*! \brief Requests a channel 
-+ * \param type type of channel to request
-+ * \param format requested channel format (codec)
-+ * \param data data to pass to the channel requester
-+ * \param status status
-+ * \param uniqueid uniqueid
-+ * Request a channel of a given type, with data as optional information used 
-+ * by the low level module. Sets the channels uniqueid to 'uniqueid'.
-+ * \return Returns an ast_channel on success, NULL on failure.
-+ */
-+struct ast_channel *ast_request_with_uniqueid(const char *type, int format, void *data, int *status, char *uniqueid);
-+
- /*!
-  * \brief Request a channel of a given type, with data as optional information used 
-  * by the low level module and attempt to place a call on it
-@@ -672,9 +684,9 @@ struct ast_channel *ast_request(const ch
-  * \return Returns an ast_channel on success or no answer, NULL on failure.  Check the value of chan->_state
-  * to know if the call was answered or not.
-  */
--struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, const char *cidnum, const char *cidname);
-+struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, int callingpres, const char *cidnum, const char *cidname, char *uniqueid);
--struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, const char *cidnum, const char *cidname, struct outgoing_helper *oh);
-+struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, int callingpres, const char *cidnum, const char *cidname, struct outgoing_helper *oh, char *uniqueid);
- /*! \brief "Requests" a channel for sending a message
-  * \param type type of channel to request
-@@ -959,6 +971,8 @@ struct ast_channel *ast_get_channel_by_e
- /*! \brief Get next channel by exten (and optionally context) and lock it */
- struct ast_channel *ast_walk_channel_by_exten_locked(const struct ast_channel *chan, const char *exten,
-                                                    const char *context);
-+/*! Get channel by uniqueid (locks channel) */
-+struct ast_channel *ast_get_channel_by_uniqueid_locked(const char *uniqueid);
- /*! ! \brief Waits for a digit
-  * \param c channel to wait for a digit on
---- a/main/channel.c
-+++ b/main/channel.c
-@@ -1035,7 +1035,7 @@ void ast_channel_undefer_dtmf(struct ast
-  */
- static struct ast_channel *channel_find_locked(const struct ast_channel *prev,
-                                              const char *name, const int namelen,
--                                             const char *context, const char *exten)
-+                                             const char *context, const char *exten, const char *uniqueid)
- {
-       const char *msg = prev ? "deadlock" : "initial deadlock";
-       int retries;
-@@ -1063,7 +1063,10 @@ static struct ast_channel *channel_find_
-                                * XXX Need a better explanation for this ...
-                                */
-                       }
--                      if (name) { /* want match by name */
-+                      if (uniqueid) { 
-+                          if (!strcasecmp(c->uniqueid, uniqueid))
-+                              break;
-+                      } else if (name) { /* want match by name */
-                               if ((!namelen && strcasecmp(c->name, name)) ||
-                                   (namelen && strncasecmp(c->name, name, namelen)))
-                                       continue;       /* name match failed */
-@@ -1118,39 +1121,44 @@ static struct ast_channel *channel_find_
- /*! \brief Browse channels in use */
- struct ast_channel *ast_channel_walk_locked(const struct ast_channel *prev)
- {
--      return channel_find_locked(prev, NULL, 0, NULL, NULL);
-+      return channel_find_locked(prev, NULL, 0, NULL, NULL, NULL);
- }
- /*! \brief Get channel by name and lock it */
- struct ast_channel *ast_get_channel_by_name_locked(const char *name)
- {
--      return channel_find_locked(NULL, name, 0, NULL, NULL);
-+      return channel_find_locked(NULL, name, 0, NULL, NULL, NULL);
- }
- /*! \brief Get channel by name prefix and lock it */
- struct ast_channel *ast_get_channel_by_name_prefix_locked(const char *name, const int namelen)
- {
--      return channel_find_locked(NULL, name, namelen, NULL, NULL);
-+      return channel_find_locked(NULL, name, namelen, NULL, NULL, NULL);
- }
- /*! \brief Get next channel by name prefix and lock it */
- struct ast_channel *ast_walk_channel_by_name_prefix_locked(const struct ast_channel *chan, const char *name,
-                                                          const int namelen)
- {
--      return channel_find_locked(chan, name, namelen, NULL, NULL);
-+      return channel_find_locked(chan, name, namelen, NULL, NULL, NULL);
- }
- /*! \brief Get channel by exten (and optionally context) and lock it */
- struct ast_channel *ast_get_channel_by_exten_locked(const char *exten, const char *context)
- {
--      return channel_find_locked(NULL, NULL, 0, context, exten);
-+      return channel_find_locked(NULL, NULL, 0, context, exten, NULL);
- }
- /*! \brief Get next channel by exten (and optionally context) and lock it */
- struct ast_channel *ast_walk_channel_by_exten_locked(const struct ast_channel *chan, const char *exten,
-                                                    const char *context)
+ static int pri_check_restart(struct zt_pri *pri)
  {
--      return channel_find_locked(chan, NULL, 0, context, exten);
-+      return channel_find_locked(chan, NULL, 0, context, exten, NULL);
-+}
-+
-+struct ast_channel *ast_get_channel_by_uniqueid_locked(const char *uniqueid)
-+{
-+      return channel_find_locked(NULL, NULL, 0, NULL, NULL, uniqueid);
- }
- /*! \brief Wait, look for hangups and condition arg */
-@@ -1220,8 +1228,10 @@ void ast_channel_free(struct ast_channel
-               free(chan->tech_pvt);
-       }
--      if (chan->sched)
--              sched_context_destroy(chan->sched);
-+      if (chan->sched) {
-+              sched_context_destroy(chan->sched);     
-+              chan->sched = NULL;
++      if ((pri->nodetype != PRI_NETWORK) && (pri->nodetype != PRI_CPE)) {
++          return 0;
 +      }
-       ast_copy_string(name, chan->name, sizeof(name));
-@@ -3106,7 +3116,7 @@ char *ast_channel_reason2str(int reason)
-       }
- }
--struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, struct outgoing_helper *oh)
-+struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, int callingpres, const char *cid_num, const char *cid_name, struct outgoing_helper *oh, char* uniqueid)
- {
-       int dummy_outstate;
-       int cause = 0;
-@@ -3118,7 +3128,7 @@ struct ast_channel *__ast_request_and_di
-       else
-               outstate = &dummy_outstate;     /* make outstate always a valid pointer */
--      chan = ast_request(type, format, data, &cause);
-+      chan = ast_request_with_uniqueid(type, format, data, &cause, uniqueid);
-       if (!chan) {
-               ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
-               /* compute error and return */
-@@ -3141,7 +3151,7 @@ struct ast_channel *__ast_request_and_di
-                       ast_cdr_setaccount(chan, oh->account);  
+       do {
+               pri->resetpos++;
+       } while ((pri->resetpos < pri->numchans) &&
+@@ -8344,13 +8471,30 @@ static void apply_plan_to_number(char *b
        }
-       ast_set_callerid(chan, cid_num, cid_name, cid_num);
--
-+      chan->cid.cid_pres = callingpres;
-       
-       if (!chan->cdr) { /* up till now, this insertion hasn't been done. Therefore,
-@@ -3230,12 +3240,12 @@ struct ast_channel *__ast_request_and_di
-       return chan;
  }
  
--struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, const char *cidnum, const char *cidname)
-+struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, int callingpres, const char *cidnum, const char *cidname, char *uniqueid)
- {
--      return __ast_request_and_dial(type, format, data, timeout, outstate, cidnum, cidname, NULL);
-+      return __ast_request_and_dial(type, format, data, timeout, outstate, 0, cidnum, cidname, NULL, uniqueid);
- }
--struct ast_channel *ast_request(const char *type, int format, void *data, int *cause)
-+struct ast_channel *ast_request_with_uniqueid(const char *type, int format, void *data, int *cause, char *uniqueid)
- {
-       struct chanlist *chan;
-       struct ast_channel *c;
-@@ -3285,6 +3295,11 @@ struct ast_channel *ast_request(const ch
-       return NULL;
+-static int zt_setlaw(int zfd, int law)
+-{
+-      int res;
+-      res = ioctl(zfd, ZT_SETLAW, &law);
+-      if (res)
+-              return res;
+-      return 0;
++static void pri_make_callerid(struct zt_pri *pri, char *callerid, int callerid_len, char *callingnum, int callingnum_len, int callingplan, int callingpres, int stripmsd) {
++    if (callingnum && (callingnum_len > stripmsd)) {
++      callingnum += stripmsd;
++    }
++    switch (callingplan) {
++      case PRI_INTERNATIONAL_ISDN:
++          snprintf(callerid, callerid_len, "%s%s", pri->internationalprefix, callingnum);
++          break;
++      case PRI_NATIONAL_ISDN:
++          snprintf(callerid, callerid_len, "%s%s", pri->nationalprefix, callingnum);
++          break;
++      case PRI_LOCAL_ISDN:
++          snprintf(callerid, callerid_len, "%s%s", pri->localprefix, callingnum);
++          break;
++      case PRI_PRIVATE:
++          snprintf(callerid, callerid_len, "%s%s", pri->privateprefix, callingnum);
++          break;
++      case PRI_UNKNOWN:
++          snprintf(callerid, callerid_len, "%s%s", pri->unknownprefix, callingnum);
++          break;
++      default:
++          snprintf(callerid, callerid_len, "%s", callingnum);
++          break;
++    }
  }
  
-+struct ast_channel *ast_request(const char *type, int format, void *data, int *cause)
-+{
-+    return ast_request_with_uniqueid(type, format, data, cause, NULL);
-+}
-+
- int ast_call(struct ast_channel *chan, char *addr, int timeout)
- {
-       /* Place an outgoing call, but don't wait any longer than timeout ms before returning.
-@@ -3672,7 +3687,7 @@ int ast_do_masquerade(struct ast_channel
-       ast_string_field_set(clone, name, masqn);
-       
-       /* Notify any managers of the change, first the masq then the other */
--      manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", newn, masqn, clone->uniqueid);
-+      manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\nNewUniqueid: %s\r\n", newn, masqn, clone->uniqueid, original->uniqueid);
-       manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", orig, newn, original->uniqueid);
-       /* Swap the technologies */     
---- a/apps/app_parkandannounce.c
-+++ b/apps/app_parkandannounce.c
-@@ -182,7 +182,7 @@ static int parkandannounce_exec(struct a
-       memset(&oh, 0, sizeof(oh));
-       oh.parent_channel = chan;
-       oh.vars = ast_variable_new("_PARKEDAT", buf);
--      dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, chan->cid.cid_num, chan->cid.cid_name, &oh);
-+      dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, 0, chan->cid.cid_num, chan->cid.cid_name, &oh, NULL);
-       if(dchan) {
-               if(dchan->_state == AST_STATE_UP) {
---- a/include/asterisk/pbx.h
-+++ b/include/asterisk/pbx.h
-@@ -717,9 +717,17 @@ int ast_async_goto_by_name(const char *c
- int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel);
- /*! Synchronously or asynchronously make an outbound call and send it to a
-+   particular extension (extended version with callinpres and uniqueid) */
-+int ast_pbx_outgoing_exten2(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, char *uniqueid);
-+
-+/*! Synchronously or asynchronously make an outbound call and send it to a
-    particular application with given extension */
- int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel);
-+/*! Synchronously or asynchronously make an outbound call and send it to a
-+   particular application with given extension (extended version with callinpres and uniqueid) */
-+int ast_pbx_outgoing_app2(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, char *uniqueid);
-+
- /*!
-  * \brief Evaluate a condition
-  *
---- a/main/pbx.c
-+++ b/main/pbx.c
-@@ -4985,7 +4985,7 @@ static int ast_pbx_outgoing_cdr_failed(v
-       return 0;  /* success */
- }
--int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel)
-+int ast_pbx_outgoing_exten2(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel, char *uniqueid)
- {
-       struct ast_channel *chan;
-       struct async_stat *as;
-@@ -4995,7 +4995,7 @@ int ast_pbx_outgoing_exten(const char *t
-       if (sync) {
-               LOAD_OH(oh);
--              chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
-+              chan = __ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
-               if (channel) {
-                       *channel = chan;
-                       if (chan)
-@@ -5080,7 +5080,7 @@ int ast_pbx_outgoing_exten(const char *t
-                       res = -1;
-                       goto outgoing_exten_cleanup;
-               }
--              chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name);
-+              chan = ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, uniqueid);
-               if (channel) {
-                       *channel = chan;
-                       if (chan)
-@@ -5120,6 +5120,10 @@ outgoing_exten_cleanup:
-       return res;
- }
-+int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel)
-+{
-+    return ast_pbx_outgoing_exten2(type, format, data, timeout, context, exten, priority, reason, sync, 0, cid_num, cid_name, vars, account, channel, NULL);
-+}
- struct app_tmp {
-       char app[256];
-       char data[256];
-@@ -5144,7 +5148,7 @@ static void *ast_pbx_run_app(void *data)
-       return NULL;
- }
--int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
-+int ast_pbx_outgoing_app2(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, char *uniqueid)
- {
-       struct ast_channel *chan;
-       struct app_tmp *tmp;
-@@ -5163,10 +5167,10 @@ int ast_pbx_outgoing_app(const char *typ
-               goto outgoing_app_cleanup;
-       }
-       if (sync) {
--              chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
-+              chan = __ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
-               if (chan) {
-                       if (chan->cdr) { /* check if the channel already has a cdr record, if not give it one */
--                              ast_log(LOG_WARNING, "%s already has a call record??\n", chan->name);
-+                              ast_log(LOG_WARNING, "%s already has a call detail record??\n", chan->name);
-                       } else {
-                               chan->cdr = ast_cdr_alloc();   /* allocate a cdr for the channel */
-                               if(!chan->cdr) {
-@@ -5247,7 +5251,7 @@ int ast_pbx_outgoing_app(const char *typ
-                       res = -1;
-                       goto outgoing_app_cleanup;
-               }
--              chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
-+              chan = __ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
-               if (!chan) {
-                       free(as);
-                       res = -1;
-@@ -5287,6 +5291,10 @@ outgoing_app_cleanup:
-       return res;
- }
-+int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
-+{
-+    return ast_pbx_outgoing_app2(type, format, data, timeout, app, appdata, reason, sync, 0, cid_num, cid_name, vars, account, locked_channel, NULL);
-+}
- void __ast_context_destroy(struct ast_context *con, const char *registrar)
- {
-       struct ast_context *tmp, *tmpl=NULL;
---- a/res/res_monitor.c
-+++ b/res/res_monitor.c
-@@ -337,6 +337,11 @@ int ast_monitor_stop(struct ast_channel 
-                       result = ast_safe_system(tmp);
-                       if (result == -1)
-                               ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
-+                      manager_event(EVENT_FLAG_CALL, "MonitorStopped",
-+                                          "Channel: %s\r\n"
-+                                          "Uniqueid: %s\r\n"
-+                                          "Result: %d\r\n"
-+                                      ,chan->name, chan->uniqueid, result);
-               }
-               
-               free(chan->monitor->format);
-@@ -503,18 +508,28 @@ static int start_monitor_action(struct m
-       const char *fname = astman_get_header(m, "File");
-       const char *format = astman_get_header(m, "Format");
-       const char *mix = astman_get_header(m, "Mix");
-+      const char *uniqueid = astman_get_header(m, "Uniqueid");
-       const char *target_url = astman_get_header(m, "TargetURL");
-       const char *target_script = astman_get_header(m, "TargetScript");
-       char *d;
-       
--      if (ast_strlen_zero(name)) {
--              astman_send_error(s, m, "No channel specified");
-+      if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
-+              astman_send_error(s, m, "No channel/uniqueid specified");
-+              return 0;
-+      }
-+
-+      if (!ast_strlen_zero(uniqueid)) {
-+          c = ast_get_channel_by_uniqueid_locked(uniqueid);
-+          if (!c) {
-+              astman_send_error(s, m, "No such uniqueid");
-               return 0;
--      }
--      c = ast_get_channel_by_name_locked(name);
--      if (!c) {
-+          }
-+      } else {
-+          c = ast_get_channel_by_name_locked(name);
-+          if (!c) {
-               astman_send_error(s, m, "No such channel");
-               return 0;
-+          }
-       }
+ static void *pri_dchannel(void *vpri)
+@@ -8530,15 +8674,44 @@ static void *pri_dchannel(void *vpri)
+                                       /* Check for an event */
+                                       x = 0;
+                                       res = ioctl(pri->fds[which], ZT_GETEVENT, &x);
+-                                      if (x) 
++                                      if ((pri->nodetype != BRI_CPE) && (pri->nodetype != BRI_CPE_PTMP)) {
++                                          /* dont annoy BRI TE mode users with layer2layer alarms */
++                                          if (x)
+                                               ast_log(LOG_NOTICE, "PRI got event: %s (%d) on %s D-channel of span %d\n", event2str(x), x, pri_order(which), pri->span);
++                                      }
+                                       /* Keep track of alarm state */ 
+                                       if (x == ZT_EVENT_ALARM) {
+                                               pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
+                                               pri_find_dchan(pri);
++                                              if ((pri->nodetype == BRI_CPE) || (pri->nodetype == BRI_CPE_PTMP)) {
++                                                  if (pri->pri) {
++                                                      for (i=0; i<pri->numchans; i++) {
++                                                          struct zt_pvt *p = pri->pvts[i];
++                                                          if (p) {
++                                                              if (p->call) {
++                                                                  if (p->pri && p->pri->pri) {
++                                                                      pri_destroycall(p->pri->pri, p->call);
++                                                                      p->call = NULL;
++                                                                      p->tei = -1;
++                                                                  } else
++                                                                      ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
++                                                              }
++                                                              if (p->owner)
++                                                                  p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
++                                                              p->inalarm = 1;
++                                                          }
++                                                      }
++                                                      pri_shutdown(pri->pri);
++                                                  }
++                                              }
+                                       } else if (x == ZT_EVENT_NOALARM) {
+-                                              pri->dchanavail[which] |= DCHAN_NOTINALARM;
+-                                              pri_restart(pri->dchans[which]);
++                                              if ((pri->nodetype == BRI_CPE) || (pri->nodetype == BRI_CPE_PTMP)) {
++                                                  pri->dchanavail[which] |= DCHAN_NOTINALARM;
++                                              //    pri->dchanavail[which] |= DCHAN_UP;
++                                              } else {
++                                                  pri->dchanavail[which] |= DCHAN_NOTINALARM;
++                                                  pri_restart(pri->dchans[which]);
++                                              }
+                                       }
+                               
+                                       if (option_debug)
+@@ -8550,8 +8723,7 @@ static void *pri_dchannel(void *vpri)
+                                       break;
+                       }
+               } else if (errno != EINTR)
+-                      ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
+-
++                      ast_log(LOG_WARNING, "pri_event returned error %d (%s) on span %d\n", errno, strerror(errno), pri->span);
+               if (e) {
+                       if (pri->debug)
+                               pri_dump_event(pri->dchans[which], e);
+@@ -8576,6 +8748,17 @@ static void *pri_dchannel(void *vpri)
  
-       if (ast_strlen_zero(fname)) {
-@@ -555,16 +570,30 @@ static int stop_monitor_action(struct ma
- {
-       struct ast_channel *c = NULL;
-       const char *name = astman_get_header(m, "Channel");
-+      const char *uniqueid = astman_get_header(m, "Uniqueid");
-       int res;
-       if (ast_strlen_zero(name)) {
-               astman_send_error(s, m, "No channel specified");
-               return 0;
-       }
--      c = ast_get_channel_by_name_locked(name);
--      if (!c) {
--              astman_send_error(s, m, "No such channel");
-+      if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
-+              astman_send_error(s, m, "No channel/uniqueid specified");
-+              return 0;
-+      }
-+      if (!ast_strlen_zero(uniqueid)) {
-+          c = ast_get_channel_by_uniqueid_locked(uniqueid);
-+          if (!c) {
-+              astman_send_error(s, m, "No such uniqueid");
-               return 0;
-+          }
-+      } else {
-+          c = ast_get_channel_by_name_locked(name);
-+          if (!c) {
-+              astman_send_error(s, m, "No such channel");
-+              return 0;
-+          }
-       }
+                       switch (e->e) {
+                       case PRI_EVENT_DCHAN_UP:
++                              if (pri->nodetype == BRI_NETWORK_PTMP) {
++                                  if (option_verbose > 3)
++                                      ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up for TEI %d\n", pri_order(which), pri->span, e->gen.tei);
++                              } else if (pri->nodetype == BRI_CPE_PTMP) {
++                                  if (option_verbose > 3)
++                                          ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
++                              } else {
++                                  if (option_verbose > 1)
++                                          ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
++                              }
 +
-       res = ast_monitor_stop(c, 1);
-       ast_channel_unlock(c);
-       if (res) {
---- a/apps/app_chanspy.c
-+++ b/apps/app_chanspy.c
-@@ -55,6 +55,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revisi
- static const char *tdesc = "Listen to a channel, and optionally whisper into it";
- static const char *app_chan = "ChanSpy";
-+static const char *app_chan2 = "ChanSpyChan";
- static const char *desc_chan = 
- "  ChanSpy([chanprefix][|options]): This application is used to listen to the\n"
- "audio from an Asterisk channel. This includes the audio coming in and\n"
-@@ -85,6 +86,27 @@ static const char *desc_chan = 
- "                    channel.\n"
- ;
+                               if (!pri->pri) pri_find_dchan(pri);
  
-+static const char *desc_uniqueid = 
-+"  ChanSpyChan(uniqueid[|options]): This application is used to listen to the\n"
-+"audio from an Asterisk channel. This includes the audio coming in and\n"
-+"out of the channel being spied on. The 'uniqueid' parameter has to be specified,\n"
-+"  While spying, the following actions may be performed:\n"
-+"    - Dialing # cycles the volume level.\n"
-+"  Options:\n"
-+"    q             - Don't play a beep when beginning to spy on a channel, or speak the\n"
-+"                    selected channel name.\n"
-+"    r[(basename)] - Record the session to the monitor spool directory. An\n"
-+"                    optional base for the filename may be specified. The\n"
-+"                    default is 'chanspy'.\n"
-+"    v([value])    - Adjust the initial volume in the range from -4 to 4. A\n"
-+"                    negative value refers to a quieter setting.\n"
-+"    w             - Enable 'whisper' mode, so the spying channel can talk to\n"
-+"                    the spied-on channel.\n"
-+"    W             - Enable 'private whisper' mode, so the spying channel can\n"
-+"                    talk to the spied-on channel but cannot listen to that\n"
-+"                    channel.\n"
-+;
-+
- static const char *app_ext = "ExtenSpy";
- static const char *desc_ext = 
- "  ExtenSpy(exten[@context][|options]): This application is used to listen to the\n"
-@@ -404,7 +426,7 @@ static int channel_spy(struct ast_channe
- }
- static struct ast_channel *next_channel(const struct ast_channel *last, const char *spec,
--                                      const char *exten, const char *context)
-+                                      const char *exten, const char *context, const char *uniqueid)
- {
-       struct ast_channel *this;
-@@ -413,6 +435,8 @@ static struct ast_channel *next_channel(
-               this = ast_walk_channel_by_name_prefix_locked(last, spec, strlen(spec));
-       else if (exten)
-               this = ast_walk_channel_by_exten_locked(last, exten, context);
-+      else if (uniqueid)
-+              this = ast_get_channel_by_uniqueid_locked(uniqueid);
-       else
-               this = ast_channel_walk_locked(last);
-@@ -427,7 +451,7 @@ static struct ast_channel *next_channel(
- static int common_exec(struct ast_channel *chan, const struct ast_flags *flags,
-                      int volfactor, const int fd, const char *mygroup, const char *spec,
--                     const char *exten, const char *context)
-+                     const char *exten, const char *context, const char *uniqueid)
- {
-       struct ast_channel *peer, *prev, *next;
-       char nameprefix[AST_NAME_STRLEN];
-@@ -466,9 +490,9 @@ static int common_exec(struct ast_channe
-               waitms = 100;
-               peer = prev = next = NULL;
--              for (peer = next_channel(peer, spec, exten, context);
-+              for (peer = next_channel(peer, spec, exten, context, NULL);
-                    peer;
--                   prev = peer, peer = next ? next : next_channel(peer, spec, exten, context), next = NULL) {
-+                   prev = peer, peer = next ? next : next_channel(peer, spec, exten, context, NULL), next = NULL) {
-                       const char *group;
-                       int igrp = !mygroup;
-                       char *groups[25];
-@@ -625,7 +649,7 @@ static int chanspy_exec(struct ast_chann
-               }
-       }
--      res = common_exec(chan, &flags, volfactor, fd, mygroup, spec, NULL, NULL);
-+      res = common_exec(chan, &flags, volfactor, fd, mygroup, spec, NULL, NULL, NULL);
-       if (fd)
-               close(fd);
-@@ -710,7 +734,92 @@ static int extenspy_exec(struct ast_chan
-               }
-       }
--      res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, exten, context);
-+      res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, exten, context, NULL);
-+
-+      if (fd)
-+              close(fd);
-+
-+      if (oldwf && ast_set_write_format(chan, oldwf) < 0)
-+              ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
-+
-+      ast_module_user_remove(u);
-+
-+      return res;
-+}
-+
-+static int chanspychan_exec(struct ast_channel *chan, void *data)
-+{
-+      struct ast_module_user *u;
-+      char *options = NULL;
-+      char *uniqueid = NULL;
-+      char *argv[2];
-+      char *mygroup = NULL;
-+      char *recbase = NULL;
-+      int fd = 0;
-+      struct ast_flags flags;
-+      int oldwf = 0;
-+      int argc = 0;
-+      int volfactor = 0;
-+      int res;
-+
-+      data = ast_strdupa(data);
-+
-+      u = ast_module_user_add(chan);
-+
-+      if ((argc = ast_app_separate_args(data, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
-+              uniqueid = argv[0];
-+              if (argc > 1)
-+                      options = argv[1];
-+
-+              if (ast_strlen_zero(uniqueid)) {
-+                      ast_log(LOG_ERROR, "no uniqueid specified.\n");
-+                      ast_module_user_remove(u);
-+                      return -1;
-+              }
-+      }
-+
-+      if (options) {
-+              char *opts[OPT_ARG_ARRAY_SIZE];
-+              
-+              ast_app_parse_options(spy_opts, &flags, opts, options);
-+              if (ast_test_flag(&flags, OPTION_GROUP))
-+                      mygroup = opts[OPT_ARG_GROUP];
-+
-+              if (ast_test_flag(&flags, OPTION_RECORD) &&
-+                  !(recbase = opts[OPT_ARG_RECORD]))
-+                      recbase = "chanspy";
-+
-+              if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
-+                      int vol;
-+
-+                      if ((sscanf(opts[OPT_ARG_VOLUME], "%d", &vol) != 1) || (vol > 4) || (vol < -4))
-+                              ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
-+                      else
-+                              volfactor = vol;
-+              }
-+
-+              if (ast_test_flag(&flags, OPTION_PRIVATE))
-+                      ast_set_flag(&flags, OPTION_WHISPER);
-+      }
-+
-+      oldwf = chan->writeformat;
-+      if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
-+              ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
-+              ast_module_user_remove(u);
-+              return -1;
-+      }
-+
-+      if (recbase) {
-+              char filename[512];
-+
-+              snprintf(filename, sizeof(filename), "%s/%s.%d.raw", ast_config_AST_MONITOR_DIR, recbase, (int) time(NULL));
-+              if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644)) <= 0) {
-+                      ast_log(LOG_WARNING, "Cannot open '%s' for recording\n", filename);
-+                      fd = 0;
-+              }
-+      }
-+
-+      res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, NULL, NULL, uniqueid);
-       if (fd)
-               close(fd);
-@@ -723,14 +832,15 @@ static int extenspy_exec(struct ast_chan
-       return res;
- }
-+
- static int unload_module(void)
- {
-       int res = 0;
-       res |= ast_unregister_application(app_chan);
-+      res |= ast_unregister_application(app_chan2);
-       res |= ast_unregister_application(app_ext);
--      ast_module_user_hangup_all();
-       return res;
- }
-@@ -741,6 +851,7 @@ static int load_module(void)
-       res |= ast_register_application(app_chan, chanspy_exec, tdesc, desc_chan);
-       res |= ast_register_application(app_ext, extenspy_exec, tdesc, desc_ext);
-+      res |= ast_register_application(app_chan2, chanspychan_exec, tdesc, desc_uniqueid);
-       return res;
- }
---- a/main/manager.c
-+++ b/main/manager.c
-@@ -87,6 +87,8 @@ struct fast_originate_helper {
-       char idtext[AST_MAX_EXTENSION];
-       char account[AST_MAX_ACCOUNT_CODE];
-       int priority;
-+      int callingpres;
-+      char uniqueid[64];
-       struct ast_variable *vars;
- };
-@@ -1415,11 +1417,20 @@ static int action_hangup(struct mansessi
- {
-       struct ast_channel *c = NULL;
-       const char *name = astman_get_header(m, "Channel");
--      if (ast_strlen_zero(name)) {
--              astman_send_error(s, m, "No channel specified");
-+      const char *uniqueid = astman_get_header(m, "Uniqueid");
-+
-+      if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
-+              astman_send_error(s, m, "No channel or uniqueid specified");
-               return 0;
-       }
--      c = ast_get_channel_by_name_locked(name);
-+
-+      if (!ast_strlen_zero(uniqueid)) {
-+              c = ast_get_channel_by_uniqueid_locked(uniqueid);
-+      } else {
-+          if (!ast_strlen_zero(name))
-+              c = ast_get_channel_by_name_locked(name);
-+      }       
-+
-       if (!c) {
-               astman_send_error(s, m, "No such channel");
-               return 0;
-@@ -1670,12 +1681,18 @@ static int action_redirect(struct manses
-       const char *exten = astman_get_header(m, "Exten");
-       const char *context = astman_get_header(m, "Context");
-       const char *priority = astman_get_header(m, "Priority");
-+      const char *uniqueid = astman_get_header(m, "Uniqueid");
-+      const char *uniqueid2 = astman_get_header(m, "ExtraUniqueid");
-+      const char *exten2 = astman_get_header(m, "ExtraExten");
-+      const char *context2 = astman_get_header(m, "ExtraContext");
-+      const char *priority2 = astman_get_header(m, "ExtraPriority");
-       struct ast_channel *chan, *chan2 = NULL;
-       int pi = 0;
-+      int pi2 = 0;
-       int res;
--      if (ast_strlen_zero(name)) {
--              astman_send_error(s, m, "Channel not specified");
-+      if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
-+              astman_send_error(s, m, "Channel or Uniqueid not specified");
-               return 0;
-       }
-       if (!ast_strlen_zero(priority) && (sscanf(priority, "%d", &pi) != 1)) {
-@@ -1685,7 +1702,11 @@ static int action_redirect(struct manses
-               }
-       }
-       /* XXX watch out, possible deadlock!!! */
--      chan = ast_get_channel_by_name_locked(name);
-+      if (!ast_strlen_zero(uniqueid)) {
-+          chan = ast_get_channel_by_uniqueid_locked(uniqueid);
-+      } else {
-+          chan = ast_get_channel_by_name_locked(name);
-+      }
-       if (!chan) {
-               char buf[BUFSIZ];
-               snprintf(buf, sizeof(buf), "Channel does not exist: %s", name);
-@@ -1707,9 +1728,9 @@ static int action_redirect(struct manses
-       }
-       res = ast_async_goto(chan, context, exten, pi);
-       if (!res) {
--              if (!ast_strlen_zero(name2)) {
-+              if ((!ast_strlen_zero(name2)) || (!ast_strlen_zero(uniqueid2))){
-                       if (chan2)
--                              res = ast_async_goto(chan2, context, exten, pi);
-+                              res = ast_async_goto(chan2, context2, exten2, pi2);
-                       else
-                               res = -1;
-                       if (!res)
-@@ -1788,15 +1809,15 @@ static void *fast_originate(void *data)
-       char requested_channel[AST_CHANNEL_NAME];
-       if (!ast_strlen_zero(in->app)) {
--              res = ast_pbx_outgoing_app(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->app, in->appdata, &reason, 1, 
-+              res = ast_pbx_outgoing_app2(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->app, in->appdata, &reason, 1, in->callingpres,
-                       S_OR(in->cid_num, NULL), 
-                       S_OR(in->cid_name, NULL),
--                      in->vars, in->account, &chan);
-+                      in->vars, in->account, &chan, in->uniqueid);
-       } else {
--              res = ast_pbx_outgoing_exten(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1, 
-+              res = ast_pbx_outgoing_exten2(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1, in->callingpres,
-                       S_OR(in->cid_num, NULL), 
-                       S_OR(in->cid_name, NULL),
--                      in->vars, in->account, &chan);
-+                      in->vars, in->account, &chan, in->uniqueid);
-       }
-       if (!chan)
-@@ -1856,6 +1877,7 @@ static int action_originate(struct manse
-       const char *appdata = astman_get_header(m, "Data");
-       const char *async = astman_get_header(m, "Async");
-       const char *id = astman_get_header(m, "ActionID");
-+      const char *callingpres = astman_get_header(m, "CallingPres");
-       struct ast_variable *vars = astman_get_variables(m);
-       char *tech, *data;
-       char *l = NULL, *n = NULL;
-@@ -1865,6 +1887,9 @@ static int action_originate(struct manse
-       int reason = 0;
-       char tmp[256];
-       char tmp2[256];
-+      char *uniqueid;
-+      int cpresi = 0;
-+      char idText[256] = "";
-       
-       pthread_t th;
-       pthread_attr_t attr;
-@@ -1882,6 +1907,10 @@ static int action_originate(struct manse
-               astman_send_error(s, m, "Invalid timeout\n");
-               return 0;
-       }
-+      if (!ast_strlen_zero(callingpres) && (sscanf(callingpres, "%d", &cpresi) != 1)) {
-+              astman_send_error(s, m, "Invalid CallingPres\n");
-+              return 0;
-+      }
-       ast_copy_string(tmp, name, sizeof(tmp));
-       tech = tmp;
-       data = strchr(tmp, '/');
-@@ -1901,6 +1930,7 @@ static int action_originate(struct manse
-               if (ast_strlen_zero(l))
-                       l = NULL;
-       }
-+      uniqueid = ast_alloc_uniqueid();
-       if (ast_true(async)) {
-               struct fast_originate_helper *fast = ast_calloc(1, sizeof(*fast));
-               if (!fast) {
-@@ -1920,8 +1950,10 @@ static int action_originate(struct manse
-                       ast_copy_string(fast->context, context, sizeof(fast->context));
-                       ast_copy_string(fast->exten, exten, sizeof(fast->exten));
-                       ast_copy_string(fast->account, account, sizeof(fast->account));
-+                      ast_copy_string(fast->uniqueid, uniqueid, sizeof(fast->uniqueid));
-                       fast->timeout = to;
-                       fast->priority = pi;
-+                      fast->callingpres = cpresi;
-                       pthread_attr_init(&attr);
-                       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-                       if (ast_pthread_create(&th, &attr, fast_originate, fast)) {
-@@ -1932,19 +1964,28 @@ static int action_originate(struct manse
-                       pthread_attr_destroy(&attr);
-               }
-       } else if (!ast_strlen_zero(app)) {
--              res = ast_pbx_outgoing_app(tech, AST_FORMAT_SLINEAR, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL);
-+              res = ast_pbx_outgoing_app2(tech, AST_FORMAT_SLINEAR, data, to, app, appdata, &reason, 1, cpresi, l, n, vars, account, NULL, uniqueid);
-       } else {
-               if (exten && context && pi)
--                      res = ast_pbx_outgoing_exten(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL);
-+                      res = ast_pbx_outgoing_exten2(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 1, cpresi, l, n, vars, account, NULL, uniqueid);
-               else {
-                       astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
-                       return 0;
-               }
-       }   
--      if (!res)
--              astman_send_ack(s, m, "Originate successfully queued");
--      else
-+      if (!res) {
-+              if (id && !ast_strlen_zero(id)) {
-+                          snprintf(idText,256,"ActionID: %s\r\n",id);
-+              }
-+              ast_cli(s->fd, "Response: Success\r\n"
-+                                  "%s"
-+                                 "Message: Originate successfully queued\r\n"
-+                                 "Uniqueid: %s\r\n"
-+                                 "\r\n",
-+                                  idText, uniqueid);
-+      } else {
-               astman_send_error(s, m, "Originate failed");
-+      }
-       return 0;
- }
---- a/include/asterisk/channel.h
-+++ b/include/asterisk/channel.h
-@@ -89,6 +89,9 @@
- #include "asterisk/abstract_jb.h"
-+/* Max length of the uniqueid */
-+#define AST_MAX_UNIQUEID 64
-+
- #include <unistd.h>
- #ifdef POLLCOMPAT 
- #include "asterisk/poll-compat.h"
-@@ -1004,6 +1007,8 @@ int ast_waitfordigit_full(struct ast_cha
- int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders);
- int ast_readstring_full(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders, int audiofd, int ctrlfd);
-+char *ast_alloc_uniqueid(void);
-+
- /*! \brief Report DTMF on channel 0 */
- #define AST_BRIDGE_DTMF_CHANNEL_0             (1 << 0)                
- /*! \brief Report DTMF on channel 1 */
---- a/main/channel.c
-+++ b/main/channel.c
-@@ -724,6 +724,15 @@ static const struct ast_channel_tech nul
-       .description = "Null channel (should not see this)",
- };
-+/*! \brief Create a uniqueid */
-+char *ast_alloc_uniqueid(void) {
-+   char *uniqueid;
-+   uniqueid = malloc(64);
-+   if (!uniqueid) return NULL;
-+   snprintf(uniqueid, 63, "%s-%d-%li.%d", ast_config_AST_SYSTEM_NAME, ast_mainpid, (long)time(NULL), ast_atomic_fetchadd_int(&uniqueint, 1));
-+   return uniqueid;
-+}
-+
- /*! \brief Create a new channel structure */
- struct ast_channel *ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const int amaflag, const char *name_fmt, ...)
- {
---- a/include/asterisk/features.h
-+++ b/include/asterisk/features.h
-@@ -47,6 +47,8 @@ struct ast_call_feature {
- };
-+extern int ast_autoanswer_login(struct ast_channel *chan, void *data);
-+extern int ast_masq_autoanswer_login(struct ast_channel *rchan, void *data);
- /*! \brief Park a call and read back parked location 
-  *  \param chan the channel to actually be parked
---- a/res/res_features.c
-+++ b/res/res_features.c
-@@ -11,6 +11,10 @@
-  * the project provides a web site, mailing lists and IRC
-  * channels for your use.
-  *
-+ * Copyright (C) 2004, Junghanns.NET GmbH
-+ *
-+ * Klaus-Peter Junghanns <kpj@junghanns.net>
-+ *
-  * This program is free software, distributed under the terms of
-  * the GNU General Public License Version 2. See the LICENSE file
-  * at the top of the source tree.
-@@ -128,6 +132,20 @@ static char *descrip2 = "Park():"
- "it already exists. In that case, execution will continue at next\n"
- "priority.\n" ;
-+static char *autoanswerlogin = "AutoanswerLogin";
-+
-+static char *synopsis3 = "Log in for autoanswer";
-+
-+static char *descrip3 = "AutoanswerLogin([context]|exten):"
-+"Used to login to the autoanswer application for an extension.\n";
-+
-+static char *autoanswer = "Autoanswer";
-+
-+static char *synopsis4 = "Autoanswer a call";
-+
-+static char *descrip4 = "Autoanswer([context]|exten):"
-+"Used to autoanswer a call for an extension.\n";
-+
- static struct ast_app *monitor_app = NULL;
- static int monitor_ok = 1;
-@@ -146,6 +164,23 @@ struct parkeduser {
-       struct parkeduser *next;
- };
-+/* auto answer user */
-+struct aauser {
-+      struct ast_channel *chan;
-+      struct timeval start;
-+      /* waiting on this extension/context */
-+      char exten[AST_MAX_EXTENSION];
-+      char context[AST_MAX_EXTENSION];
-+      int priority;
-+      int notquiteyet;
-+      struct aauser *next;
-+};
-+
-+ 
-+static struct aauser *aalot;
-+AST_MUTEX_DEFINE_STATIC(autoanswer_lock);
-+static pthread_t autoanswer_thread;
-+
- static struct parkeduser *parkinglot;
- AST_MUTEX_DEFINE_STATIC(parking_lock);        /*!< protects all static variables above */
-@@ -401,11 +436,13 @@ static int park_call_full(struct ast_cha
-               "From: %s\r\n"
-               "Timeout: %ld\r\n"
-               "CallerID: %s\r\n"
--              "CallerIDName: %s\r\n",
-+              "CallerIDName: %s\r\n"
-+              "Uniqueid: %s\r\n",
-               pu->parkingexten, pu->chan->name, peer ? peer->name : "",
-               (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
-               S_OR(pu->chan->cid.cid_num, "<unknown>"),
--              S_OR(pu->chan->cid.cid_name, "<unknown>")
-+              S_OR(pu->chan->cid.cid_name, "<unknown>"),
-+              pu->chan->uniqueid
-               );
-       if (peer && adsipark && ast_adsi_available(peer)) {
-@@ -1628,11 +1665,13 @@ static void post_manager_event(const cha
-               "Exten: %s\r\n"
-               "Channel: %s\r\n"
-               "CallerID: %s\r\n"
--              "CallerIDName: %s\r\n\r\n",
-+              "CallerIDName: %s\r\n"
-+              "Uniqueid: %s\r\n\r\n",
-               parkingexten, 
-               chan->name,
-               S_OR(chan->cid.cid_num, "<unknown>"),
--              S_OR(chan->cid.cid_name, "<unknown>")
-+              S_OR(chan->cid.cid_name, "<unknown>"),
-+              chan->uniqueid
-               );
- }
-@@ -1887,10 +1926,12 @@ static int park_exec(struct ast_channel 
-                       "Channel: %s\r\n"
-                       "From: %s\r\n"
-                       "CallerID: %s\r\n"
--                      "CallerIDName: %s\r\n",
-+                      "CallerIDName: %s\r\n"
-+                      "Uniqueid: %s\r\n",
-                       pu->parkingexten, pu->chan->name, chan->name,
-                       S_OR(pu->chan->cid.cid_num, "<unknown>"),
--                      S_OR(pu->chan->cid.cid_name, "<unknown>")
-+                      S_OR(pu->chan->cid.cid_name, "<unknown>"),
-+                      pu->chan->uniqueid
-                       );
-               free(pu);
-@@ -2044,15 +2085,10 @@ static struct ast_cli_entry cli_show_fea
-       handle_showfeatures, NULL,
-       NULL };
--static struct ast_cli_entry cli_features[] = {
--      { { "feature", "show", NULL },
--      handle_showfeatures, "Lists configured features",
--      showfeatures_help, NULL, &cli_show_features_deprecated },
-+static char showautoanswer_help[] =
-+"Usage: show autoanswer\n"
-+"       Lists currently logged in autoanswer users.\n";
--      { { "show", "parkedcalls", NULL },
--      handle_parkedcalls, "Lists parked calls",
--      showparked_help },
--};
- /*! \brief Dump lot status */
- static int manager_parking_status( struct mansession *s, const struct message *m)
-@@ -2076,12 +2112,13 @@ static int manager_parking_status( struc
-                       "Timeout: %ld\r\n"
-                       "CallerID: %s\r\n"
-                       "CallerIDName: %s\r\n"
-+                      "Unqiueid: %s\r\n\r\n"
-                       "%s"
-                       "\r\n",
-                       cur->parkingnum, cur->chan->name, cur->peername,
-                       (long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
-                       S_OR(cur->chan->cid.cid_num, ""),       /* XXX in other places it is <unknown> */
--                      S_OR(cur->chan->cid.cid_name, ""),
-+                      S_OR(cur->chan->cid.cid_name, ""), cur->chan->uniqueid,
-                       idText);
-       }
-@@ -2156,6 +2193,427 @@ static int manager_park(struct mansessio
-       return 0;
- }
-+static int handle_autoanswer(int fd, int argc, char *argv[])
-+{
-+      struct aauser *cur;
-+
-+      ast_cli(fd, "%25s %10s %15s \n", "Channel"
-+              , "Extension", "Context");
-+
-+      ast_mutex_lock(&autoanswer_lock);
-+
-+      cur=aalot;
-+      while(cur) {
-+              ast_cli(fd, "%25s %10s %15s\n",cur->chan->name, cur->exten, cur->context);
-+
-+              cur = cur->next;
-+      }
-+
-+      ast_mutex_unlock(&autoanswer_lock);
-+
-+      return RESULT_SUCCESS;
-+}
-+
-+static struct ast_cli_entry cli_features[] = {
-+      { { "feature", "list", NULL },
-+      handle_showfeatures, "Lists configured features",
-+      showfeatures_help, NULL, &cli_show_features_deprecated },
-+
-+      { { "show", "parkedcalls", NULL },
-+      handle_parkedcalls, "Lists parked calls",
-+      showparked_help },
-+
-+      { { "show", "autoanswer", NULL },
-+      handle_autoanswer, "Lists autoanswer users",
-+      showautoanswer_help },
-+};
-+int ast_masq_autoanswer_login(struct ast_channel *rchan, void *data)
-+{
-+      struct ast_channel *chan;
-+      struct ast_frame *f;
-+      /* Make a new, fake channel that we'll use to masquerade in the real one */
-+      chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Autoanswer/%s", rchan->name);
-+      if (chan) {
-+              /* Let us keep track of the channel name */
-+              ast_string_field_build(chan, name, "Autoanswer/%s",rchan->name);
-+              /* Make formats okay */
-+              chan->readformat = rchan->readformat;
-+              chan->writeformat = rchan->writeformat;
-+              ast_channel_masquerade(chan, rchan);
-+              /* Setup the extensions and such */
-+              strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
-+              strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
-+              chan->priority = rchan->priority;
-+              /* might be dirty but we want trackable channels */
-+              ast_string_field_build(chan, uniqueid, "%s",rchan->uniqueid);
-+              /* Make the masq execute */
-+              f = ast_read(chan);
-+              if (f)
-+                      ast_frfree(f);
-+              ast_autoanswer_login(chan, data);
-+      } else {
-+              ast_log(LOG_WARNING, "Unable to create aa channel\n");
-+              return -1;
-+      }
-+      return 0;
-+}
-+
-+static int autoanswer_login_exec(struct ast_channel *chan, void *data)
-+{
-+      int res=0;
-+      struct ast_module_user *u;
-+
-+      u = ast_module_user_add(chan);
-+      if (!data) {
-+              ast_log(LOG_WARNING, "AutoanswerLogin requires an argument (extension number)\n");
-+              return -1;
-+      }
-+      res = ast_masq_autoanswer_login(chan, data);
-+      ast_module_user_remove(u);
-+      return res; 
-+}
-+
-+int ast_autoanswer_login(struct ast_channel *chan, void *data)
-+{
-+      /* We put the user in the parking list, then wake up the parking thread to be sure it looks
-+         after these channels too */
-+      struct ast_context *con;
-+      char exten[AST_MAX_EXTENSION];
-+      struct aauser *pu,*pl = NULL;
-+      char *s, *stringp, *aacontext, *aaexten = NULL;
-+
-+      s = ast_strdupa((void *) data);
-+      stringp=s;
-+      aacontext = strsep(&stringp, "|");
-+      aaexten = strsep(&stringp, "|");
-+      if (!aaexten) {
-+          aaexten = aacontext;
-+          aacontext = NULL;
-+      }
-+      if (!aaexten) {
-+              ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
-+              return -1;
-+      } else {
-+              if (!aacontext) {
-+                      aacontext = "default";
-+              }
-+      }
-+
-+      ast_mutex_lock(&autoanswer_lock);
-+      pu = aalot;
-+      while(pu) {
-+              if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
-+                      if (pl)
-+                              pl->next = pu->next;
-+                      else
-+                              aalot = pu->next;
-+                      break;
-+              }
-+              pl = pu;
-+              pu = pu->next;
-+      }
-+      ast_mutex_unlock(&autoanswer_lock);
-+      if (pu) {
-+          ast_log(LOG_NOTICE, "Logout old Channel %s for %s@%s.\n",pu->chan->name, pu->exten, pu->context);
-+          manager_event(EVENT_FLAG_CALL, "AutoanswerLogout",
-+                                          "Channel: %s\r\n"
-+                                          "Uniqueid: %s\r\n"
-+                                          "Context: %s\r\n"
-+                                          "Exten: %s\r\n"
-+                                      ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
-+          ast_hangup(pu->chan);
-+          free(pu);
-+      }
-+      pu = malloc(sizeof(struct aauser));
-+      if (pu) {
-+              memset(pu, 0, sizeof(pu));
-+              ast_mutex_lock(&autoanswer_lock);
-+              chan->appl = "Autoanswer";
-+              chan->data = NULL; 
-+
-+              pu->chan = chan;
-+              if (chan->_state != AST_STATE_UP) {
-+                  ast_answer(chan);
-+              }
-+
-+              /* Start music on hold */
-+              ast_moh_start(pu->chan, NULL, NULL);
-+              gettimeofday(&pu->start, NULL);
-+              strncpy(pu->exten, aaexten, sizeof(pu->exten)-1);
-+              strncpy(pu->context, aacontext, sizeof(pu->exten)-1);
-+              pu->next = aalot;
-+              aalot = pu;
-+              con = ast_context_find(aacontext);
-+              if (!con) {
-+                      con = ast_context_create(NULL,aacontext, registrar);
-+                      if (!con) {
-+                              ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", aacontext);
-+                      }
-+              }
-+              if (con) {
-+                      snprintf(exten, sizeof(exten), "%s", aaexten);
-+                      ast_add_extension2(con, 1, exten, 1, NULL, NULL, autoanswer, strdup((char *)data), free, registrar);
-+              }
-+
-+              ast_mutex_unlock(&autoanswer_lock);
-+              /* Wake up the (presumably select()ing) thread */
-+              pthread_kill(autoanswer_thread, SIGURG);
-+              if (option_verbose > 1) 
-+                      ast_verbose(VERBOSE_PREFIX_2 "Autoanswer login from %s for %s@%s.\n", pu->chan->name, pu->exten, pu->context);
-+                      manager_event(EVENT_FLAG_CALL, "AutoanswerLogin",
-+                                "Channel: %s\r\n"
-+                                "Uniqueid: %s\r\n"
-+                              "Context: %s\r\n"
-+                              "Exten: %s\r\n"
-+                              ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
-+
-+                      return 0;
-+      } else {
-+              ast_log(LOG_WARNING, "Out of memory\n");
-+              return -1;
-+      }
-+      return 0;
-+}
-+
-+static void autoanswer_reregister_extensions(void)
-+{
-+      struct aauser *cur;
-+      struct ast_context *con;
-+      char exten[AST_MAX_EXTENSION];
-+      char args[AST_MAX_EXTENSION];
+                               /* Note presense of D-channel */
+@@ -8594,6 +8777,12 @@ static void *pri_dchannel(void *vpri)
+                                       }
+                               break;
+                       case PRI_EVENT_DCHAN_DOWN:
++                              if (pri->nodetype == BRI_NETWORK_PTMP) {
++                                  if (option_verbose > 3)
++                                      ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down for TEI %d\n", pri_order(which), pri->span, e->gen.tei);
++                                  // PTMP BRIs have N dchans, handled by libpri
++                                  if (e->gen.tei == 0) break;
++                              }
+                               pri_find_dchan(pri);
+                               if (!pri_is_up(pri)) {
+                                       pri->resetting = 0;
+@@ -8601,16 +8790,18 @@ static void *pri_dchannel(void *vpri)
+                                       for (i = 0; i < pri->numchans; i++) {
+                                               struct zt_pvt *p = pri->pvts[i];
+                                               if (p) {
++                                                  if ((p->tei == e->gen.tei) || (pri->nodetype != BRI_NETWORK_PTMP)) {
+                                                       if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
+                                                               /* T309 is not enabled : hangup calls when alarm occurs */
+                                                               if (p->call) {
+                                                                       if (p->pri && p->pri->pri) {
+-                                                                              pri_hangup(p->pri->pri, p->call, -1);
++                                                                              pri_hangup(p->pri->pri, p->call, -1, -1);
+                                                                               pri_destroycall(p->pri->pri, p->call);
+                                                                               p->call = NULL;
+                                                                       } else
+                                                                               ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
+                                                               }
++                                                              p->tei = -1;
+                                                               if (p->realcall) {
+                                                                       pri_hangup_all(p->realcall, pri);
+                                                               } else if (p->owner)
+@@ -8619,6 +8810,7 @@ static void *pri_dchannel(void *vpri)
+                                                       p->inalarm = 1;
+                                               }
+                                       }
++                                  }
+                               }
+                               break;
+                       case PRI_EVENT_RESTART:
+@@ -8653,8 +8845,8 @@ static void *pri_dchannel(void *vpri)
+                                                               pri_destroycall(pri->pri, pri->pvts[x]->call);
+                                                               pri->pvts[x]->call = NULL;
+                                                       }
+-                                                      if (pri->pvts[chanpos]->realcall) 
+-                                                              pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
++                                                      if (pri->pvts[x]->realcall)
++                                                              pri_hangup_all(pri->pvts[x]->realcall, pri);
+                                                       else if (pri->pvts[x]->owner)
+                                                               pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+                                                       ast_mutex_unlock(&pri->pvts[x]->lock);
+@@ -8688,7 +8880,6 @@ static void *pri_dchannel(void *vpri)
+                                       }
+                               }
+                               break;
+-                              
+                       case PRI_EVENT_INFO_RECEIVED:
+                               chanpos = pri_find_principle(pri, e->ring.channel);
+                               if (chanpos < 0) {
+@@ -8697,9 +8888,11 @@ static void *pri_dchannel(void *vpri)
+                               } else {
+                                       chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
+                                       if (chanpos > -1) {
++//                                    ast_log(LOG_NOTICE, "INFO received on  channel %d/%d span %d\n",
++//                                            PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
+                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
+                                               /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
+-                                              if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
++                                              if (pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
+                                                       /* how to do that */
+                                                       int digitlen = strlen(e->ring.callednum);
+                                                       char digit;
+@@ -8711,6 +8904,14 @@ static void *pri_dchannel(void *vpri)
+                                                                       zap_queue_frame(pri->pvts[chanpos], &f, pri);
+                                                               }
+                                                       }
++                                                      if (!pri->overlapdial) {
++                                                          strncat(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
++                                                          if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten + 1)) {
++                                                              tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
++                                                          } else {
++                                                              tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
++                                                          }
++                                                      }
+                                               }
+                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+                                       }
+@@ -8718,36 +8919,59 @@ static void *pri_dchannel(void *vpri)
+                               break;
+                       case PRI_EVENT_RING:
+                               crv = NULL;
+-                              if (e->ring.channel == -1)
++                              if (e->ring.channel == -1) {
++                                      /* if no channel specified find one empty */
+                                       chanpos = pri_find_empty_chan(pri, 1);
+-                              else
++                              } else {
+                                       chanpos = pri_find_principle(pri, e->ring.channel);
++                              }
+                               /* if no channel specified find one empty */
+                               if (chanpos < 0) {
+-                                      ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 
+-                                              PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
++                                      /* no channel specified and no free channel. this is a callwating SETUP */
++                                      if (e->ring.channel <= 0) {
++                                          if (option_verbose > 2)
++                                              ast_verbose(VERBOSE_PREFIX_3 "Ignoring callwaiting SETUP on channel %d/%d span %d %d\n", PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span, e->ring.channel);
++                                          pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_USER_BUSY, -1);
++                                          break;
++                                      }
+                               } else {
++                                      /* ok, we got a b channel for this call, lock it */
+                                       ast_mutex_lock(&pri->pvts[chanpos]->lock);
+                                       if (pri->pvts[chanpos]->owner) {
+-                                              if (pri->pvts[chanpos]->call == e->ring.call) {
+-                                                      ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 
++                                          /* safety check, for messed up retransmissions? */
++                                          if (pri->pvts[chanpos]->call == e->ring.call) {
++                                              ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
+                                                               PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
+-                                                      break;
++                                              ast_mutex_unlock(&pri->pvts[chanpos]->lock);
++                                              chanpos = -1;
++                                              break;
++                                          } else {
++                                              ast_log(LOG_WARNING, "Ring requested on channel %d/%d already in use on span %d. Hanging up owner.\n",
++                                              PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
++                                              if (pri->pvts[chanpos]->realcall) {
++                                                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
+                                               } else {
+-                                                      /* This is where we handle initial glare */
+-                                                      ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d.  Attempting to renegotiating channel.\n", 
+-                                                      PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
+-                                                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+-                                                      chanpos = -1;
++                                                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
++                                                      /* XXX destroy the call here, so we can accept the retransmission as a new call */
++                                                      pri_destroycall(pri->pri, e->ring.call);
+                                               }
+-                                      }
+-                                      if (chanpos > -1)
+                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
++                                              chanpos = -1;
++                                              break;
++                                          }
++                                      }
++                                      if (chanpos > -1) {
++                                              /* everything is ok with the b channel */
++                                          ast_mutex_unlock(&pri->pvts[chanpos]->lock);
++                                      }
+                               }
+-                              if ((chanpos < 0) && (e->ring.flexible))
+-                                      chanpos = pri_find_empty_chan(pri, 1);
++                              /* actually, we already got a valid channel by now */
+                               if (chanpos > -1) {
+                                       ast_mutex_lock(&pri->pvts[chanpos]->lock);
++                                      /* dont detect dtmfs before the signalling is done */
++                                      disable_dtmf_detect(pri->pvts[chanpos]);
++                                      /* this channel is owned by this TEI */
++                                      pri->pvts[chanpos]->tei = e->ring.tei;
+                                       if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
+                                               /* Should be safe to lock CRV AFAIK while bearer is still locked */
+                                               crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
+@@ -8761,13 +8985,14 @@ static void *pri_dchannel(void *vpri)
+                                                               ast_log(LOG_WARNING, "Call received for busy CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
+                                                       } else
+                                                               ast_log(LOG_NOTICE, "Call received for unconfigured CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
+-                                                      pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
++                                                      pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE, -1);
+                                                       if (crv)
+                                                               ast_mutex_unlock(&crv->lock);
+                                                       ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+                                                       break;
+                                               }
+                                       }
++                                      /* assign call to b channel */
+                                       pri->pvts[chanpos]->call = e->ring.call;
+                                       apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
+                                       if (pri->pvts[chanpos]->use_callerid) {
+@@ -8792,34 +9017,82 @@ static void *pri_dchannel(void *vpri)
+                                       }
+                                       apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
+                                                            e->ring.redirectingnum, e->ring.callingplanrdnis);
++                                      /* get callingpres */
++                                      pri->pvts[chanpos]->cid_pres = e->ring.callingpres;
++                                      switch (e->ring.callingpres) {
++                                          case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
++                                          case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
++                                          case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
++                                          case PRES_PROHIB_NETWORK_NUMBER:
++                                              ast_copy_string(pri->pvts[chanpos]->cid_name, pri->withheldcid, sizeof(pri->pvts[chanpos]->cid_name));
++                                              break;
++                                          case PRES_NUMBER_NOT_AVAILABLE:
++                                              ast_copy_string(pri->pvts[chanpos]->cid_name, pri->nocid, sizeof(pri->pvts[chanpos]->cid_name));
++                                              break;
++                                      }
+                                       /* If immediate=yes go to s|1 */
+                                       if (pri->pvts[chanpos]->immediate) {
+                                               if (option_verbose > 2)
+                                                       ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
+                                               pri->pvts[chanpos]->exten[0] = 's';
+                                               pri->pvts[chanpos]->exten[1] = '\0';
+-                                      }
+-                                      /* Get called number */
+-                                      else if (!ast_strlen_zero(e->ring.callednum)) {
+-                                              ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
+-                                              ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
+-                                      } else if (pri->overlapdial)
+-                                              pri->pvts[chanpos]->exten[0] = '\0';
+-                                      else {
+-                                              /* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
+-                                              pri->pvts[chanpos]->exten[0] = 's';
+-                                              pri->pvts[chanpos]->exten[1] = '\0';
+-                                      }
+-                                      /* Set DNID on all incoming calls -- even immediate */
+-                                      if (!ast_strlen_zero(e->ring.callednum))
+-                                              ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
+-                                      /* No number yet, but received "sending complete"? */
+-                                      if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
++                                      } else if (ast_strlen_zero(e->ring.callednum)) {
++                                          /* called party number is empty */
++                                          if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
++                                              if (!pri->overlapdial) {
++                                                  // be able to set digittimeout for BRI phones
++                                                  pri->pvts[chanpos]->exten[0] = 's';
++                                                  pri->pvts[chanpos]->exten[1] = '\0';
++                                                  tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
++                                              } else {
++                                                  pri->pvts[chanpos]->exten[0] = '\0';
++                                              }
++                                          } else {
++                                              if (pri->nodetype == BRI_CPE) {
++                                                  /* fix for .at p2p bri lines */
++                                                  pri->pvts[chanpos]->exten[0] = 's';
++                                                  pri->pvts[chanpos]->exten[1] = '\0';
++                                              } else if (pri->overlapdial) {
++                                                  pri->pvts[chanpos]->exten[0] = '\0';
++                                              } else {
++                                                  /* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
++                                                  pri->pvts[chanpos]->exten[0] = 's';
++                                                  pri->pvts[chanpos]->exten[1] = '\0';
++                                              }
++                                          }
++                                          /* No number yet, but received "sending complete"? */
++                                          if (e->ring.complete) {
+                                               if (option_verbose > 2)
+                                                       ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
+                                               pri->pvts[chanpos]->exten[0] = 's';
+                                               pri->pvts[chanpos]->exten[1] = '\0';
+-                                      }
++                                          }
++                                      } else {
++                                              /* Get called number */
++                                              pri_make_callerid(pri, pri->pvts[chanpos]->dnid, sizeof(pri->pvts[chanpos]->dnid), e->ring.callednum, sizeof(e->ring.callednum),  e->ring.calledplan, 0, pri->pvts[chanpos]->stripmsd);
++                                              pri_make_callerid(pri, pri->pvts[chanpos]->exten, sizeof(pri->pvts[chanpos]->exten), e->ring.callednum, sizeof(e->ring.callednum), e->ring.calledplan, 0, pri->pvts[chanpos]->stripmsd);
++                                              if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
++                                                  /* if we get the next digit we should stop the dialtone */
++                                                  if (!pri->overlapdial) {
++                                                      // with overlapdial=no the exten is always prefixed by "s"
++                                                      if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten + 1)) {
++                                                          tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
++                                                      } else {
++                                                          tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
++                                                      }
++                                                  } else {
++                                                      if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten)) {
++                                                          tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
++                                                      } else {
++                                                          tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
++                                                      }
++                                                  }
++                                              }
++                                      }
++                                      /* Part 3: create channel, setup audio... */
++                                      /* Set DNID on all incoming calls -- even immediate */
++                                      if (!ast_strlen_zero(e->ring.callednum))
++                                              strncpy(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid) - 1);
+                                       /* Make sure extension exists (or in overlap dial mode, can exist) */
+                                       if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
+                                               ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
+@@ -8838,19 +9111,36 @@ static void *pri_dchannel(void *vpri)
+                                               res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
+                                               if (res < 0) 
+                                                       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
+-                                              res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
++                                              if (IS_DIGITAL(e->ring.ctype)) {
++                                                  res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[chanpos]->law);
++                                              } else {
++                                                  res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
++                                              }
+                                               if (res < 0)
+                                                       ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
+-                                              if (e->ring.complete || !pri->overlapdial) {
++                                              if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
++                                                  if (e->ring.complete || !pri->overlapdial) {
+                                                       /* Just announce proceeding */
+                                                       pri->pvts[chanpos]->proceeding = 1;
+                                                       pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
+-                                              } else {
++                                                  } else {
+                                                       if (pri->switchtype != PRI_SWITCH_GR303_TMC) 
+                                                               pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
+                                                       else
+                                                               pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
++                                                  }
++                                              } else {
++                                                      /* BRI_NETWORK | BRI_NETWORK_PTMP */
++                                                      if (pri->overlapdial || (!strcasecmp(pri->pvts[chanpos]->exten, "s"))) {
++                                                          /* send a SETUP_ACKNOWLEDGE */
++                                                          pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
++                                                      } else {
++                                                          /* send an ALERTING ??? wtf */
++                                                      //    pri_acknowledge(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
++                                                          pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
++                                                      }
+                                               }
++                                              /* overlapdial = yes  and the extension can be valid */
+                                               /* Get the use_callingpres state */
+                                               pri->pvts[chanpos]->callingpres = e->ring.callingpres;
+                                       
+@@ -8862,10 +9152,17 @@ static void *pri_dchannel(void *vpri)
+                                                               /* Set bearer and such */
+                                                               pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
+                                                               c = zt_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
++                                                              if (c && (e->ring.lowlayercompat[0] > 0)) {
++                                                                  memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
++                                                              }
+                                                               pri->pvts[chanpos]->owner = &inuse;
+                                                               ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
+                                                       } else {
+                                                               c = zt_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
++                                                              if (c && (e->ring.lowlayercompat[0] > 0)) {
++                                                                  memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
++                                                              }
++                                                              zt_enable_ec(pri->pvts[chanpos]);  /* XXX rethink */
+                                                       }
+                                                       ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+@@ -8873,6 +9170,16 @@ static void *pri_dchannel(void *vpri)
+                                                       if (!ast_strlen_zero(e->ring.callingsubaddr)) {
+                                                               pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
+                                                       }
++                                                      if (!ast_strlen_zero(e->ring.callingnum)) {
++                                                          char tmpstr[256];
++                                                          pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingnum, sizeof(e->ring.callingnum), e->ring.callingplan, e->ring.callingpres, 0);
++                                                          pbx_builtin_setvar_helper(c, "PRI_NETWORK_CID", tmpstr);
++                                                      }
++                                                      if (!ast_strlen_zero(e->ring.callingani)) {
++                                                          char tmpstr[256];
++                                                          pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingani, sizeof(e->ring.callingani), e->ring.callingplanuser, e->ring.callingpresuser, 0);
++                                                          pbx_builtin_setvar_helper(c, "PRI_USER_CID", tmpstr);
++                                                      }
+                                                       if (e->ring.ani2 >= 0) {
+                                                               snprintf(ani2str, 5, "%.2d", e->ring.ani2);
+                                                               pbx_builtin_setvar_helper(c, "ANI2", ani2str);
+@@ -8896,8 +9203,8 @@ static void *pri_dchannel(void *vpri)
+                                                       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+                                                       if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
+                                                               if (option_verbose > 2)
+-                                                                      ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
+-                                                                              plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
++                                                                      ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap %s call from '%s' to '%s' on channel %d/%d, span %d\n",
++                                                                              pri->pvts[chanpos]->digital ? "data" : "voice", plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
+                                                                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
+                                                       } else {
+                                                               ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 
+@@ -8905,15 +9212,19 @@ static void *pri_dchannel(void *vpri)
+                                                               if (c)
+                                                                       ast_hangup(c);
+                                                               else {
+-                                                                      pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
++                                                                      pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION, -1);
+                                                                       pri->pvts[chanpos]->call = NULL;
+                                                               }
+                                                       }
+                                                       pthread_attr_destroy(&attr);
+                                               } else  {
++                                                      /* overlapdial = no */
+                                                       ast_mutex_unlock(&pri->lock);
+                                                       /* Release PRI lock while we create the channel */
+                                                       c = zt_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
++                                                      if (c && (e->ring.lowlayercompat[0] > 0)) {
++                                                          memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
++                                                      }
+                                                       if (c) {
+                                                               char calledtonstr[10];
+@@ -8940,26 +9251,43 @@ static void *pri_dchannel(void *vpri)
+                                                               ast_mutex_lock(&pri->lock);
+                                                               if (option_verbose > 2)
+-                                                                      ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
+-                                                                              plancallingnum, pri->pvts[chanpos]->exten, 
++                                                                      ast_verbose(VERBOSE_PREFIX_3 "Accepting %s call from '%s' to '%s' on channel %d/%d, span %d\n",
++                                                                              pri->pvts[chanpos]->digital ? "data" : "voice", e->ring.callingnum, pri->pvts[chanpos]->exten,
+                                                                                       pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
+                                                               zt_enable_ec(pri->pvts[chanpos]);
++                                                          if(!ast_strlen_zero(e->ring.callingsubaddr)) {
++                                                              pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
++                                                          }
++                                                          if (!ast_strlen_zero(e->ring.callingnum)) {
++                                                              char tmpstr[256];
++                                                              pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingnum, sizeof(e->ring.callingnum), e->ring.callingplan, e->ring.callingpres, 0);
++                                                              pbx_builtin_setvar_helper(c, "PRI_NETWORK_CID", tmpstr);
++                                                          }
++                                                          if (!ast_strlen_zero(e->ring.callingani)) {
++                                                              char tmpstr[256];
++                                                              pri_make_callerid(pri, tmpstr,sizeof(tmpstr),  e->ring.callingani, sizeof(e->ring.callingani), e->ring.callingplanuser, e->ring.callingpresuser, 0);
++                                                              pbx_builtin_setvar_helper(c, "PRI_USER_CID", e->ring.callednum);
++                                                          }
++                                                          if (!ast_strlen_zero(e->ring.useruserinfo)) {
++                                                              pbx_builtin_setvar_helper(c, "UUI", e->ring.useruserinfo);
++                                                          }
+                                                       } else {
+                                                               ast_mutex_lock(&pri->lock);
+                                                               ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 
+                                                                       pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
+-                                                              pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
++                                                              pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION, -1);
+                                                               pri->pvts[chanpos]->call = NULL;
+                                                       }
+                                               }
+                                       } else {
++                                      /* invalid extension */
+                                               if (option_verbose > 2)
+                                                       ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist.  Rejecting call on channel %d/%d, span %d\n",
+                                                               pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 
+                                                                       pri->pvts[chanpos]->prioffset, pri->span);
+-                                              pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
++                                              pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED, -1);
+                                               pri->pvts[chanpos]->call = NULL;
+                                               pri->pvts[chanpos]->exten[0] = '\0';
+                                       }
+@@ -8968,9 +9296,9 @@ static void *pri_dchannel(void *vpri)
+                                       ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+                               } else {
+                                       if (e->ring.flexible)
+-                                              pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
++                                              pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION, -1);
+                                       else
+-                                              pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
++                                              pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL, -1);
+                               }
+                               break;
+                       case PRI_EVENT_RINGING:
+@@ -8986,7 +9314,7 @@ static void *pri_dchannel(void *vpri)
+                                       } else {
+                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
+                                               if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
+-                                                      zt_enable_ec(pri->pvts[chanpos]);
++                                              // XXX  zt_enable_ec(pri->pvts[chanpos]);
+                                                       pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
+                                                       pri->pvts[chanpos]->alerting = 1;
+                                               } else
+@@ -9018,9 +9346,16 @@ static void *pri_dchannel(void *vpri)
+                               }
+                               break;
+                       case PRI_EVENT_PROGRESS:
+-                              /* Get chan value if e->e is not PRI_EVNT_RINGING */
++                              /* Get chan value if e->e is not PRI_EVENT_RINGING */
+                               chanpos = pri_find_principle(pri, e->proceeding.channel);
+                               if (chanpos > -1) {
++                                  if ((pri->pvts[chanpos]->priindication_oob == 2) && (e->proceeding.cause == PRI_CAUSE_USER_BUSY)) {
++                                      /* received PROGRESS with cause BUSY, no inband callprogress wanted => hang up! */
++                                      if (pri->pvts[chanpos]->owner) {
++                                          pri->pvts[chanpos]->owner->hangupcause = AST_CAUSE_USER_BUSY;
++                                          pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
++                                      }
++                                  } else {
+ #ifdef PRI_PROGRESS_MASK
+                                       if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
+ #else
+@@ -9062,11 +9397,18 @@ static void *pri_dchannel(void *vpri)
+                                               pri->pvts[chanpos]->progress = 1;
+                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+                                       }
++                                  }
+                               }
+                               break;
+                       case PRI_EVENT_PROCEEDING:
+                               chanpos = pri_find_principle(pri, e->proceeding.channel);
+                               if (chanpos > -1) {
++                                  chanpos = pri_fixup_principle(pri, chanpos, e->proceeding.call);
++                                  if (chanpos < 0) {
++                                      ast_log(LOG_WARNING, "Received PROCEEDING on channel %d/%d not in use on span %d\n",
++                                              PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), pri->span);
++                                      chanpos = -1;
++                                  } else {
+                                       if (!pri->pvts[chanpos]->proceeding) {
+                                               struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
+                                               
+@@ -9091,6 +9433,7 @@ static void *pri_dchannel(void *vpri)
+                                               pri->pvts[chanpos]->proceeding = 1;
+                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+                                       }
++                                  }
+                               }
+                               break;
+                       case PRI_EVENT_FACNAME:
+@@ -9114,6 +9457,163 @@ static void *pri_dchannel(void *vpri)
+                                       }
+                               }
+                               break;                          
++                      case PRI_EVENT_SUSPEND_REQ:
++                              if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
++                                  pri_suspend_reject(pri->pri, e->suspend_req.call, "");
++                                  break;
++                              }
++                              chanpos = pri_find_principle(pri, e->suspend_req.channel);
++                              if (chanpos < 0)  {
++                                      ast_log(LOG_WARNING, "Suspend requested on unconfigured channel %d span %d\n", chanpos, pri->span);
++                                      chanpos = -1;
++                              }
 +
-+      ast_mutex_lock(&autoanswer_lock);
++                              if (chanpos > -1) {
++                                  ast_mutex_lock(&pri->pvts[chanpos]->lock);
++                                  if (pri->pvts[chanpos]->owner) {
++                                      if (ast_bridged_channel(pri->pvts[chanpos]->owner)) {
++                                          struct zt_suspended_call *zpc;
++                                          char tmpstr[256];
++                                          zpc = malloc(sizeof(struct zt_suspended_call));
++                                          if (!zpc) {
++                                              ast_log(LOG_ERROR, "unable to malloc zt_suspended_call\n");
++                                              break;
++                                          }
++                                          strncpy(zpc->msn,  pri->pvts[chanpos]->cid_num, sizeof(zpc->msn));
++                                          strncpy(zpc->callid,  e->suspend_req.callid, sizeof(zpc->callid));
++                                          ast_masq_park_call(ast_bridged_channel(pri->pvts[chanpos]->owner), NULL, 0, &zpc->parked_at);
++                                          zpc->next = pri->suspended_calls;
++                                          pri->suspended_calls = zpc;
++                                          snprintf(tmpstr, sizeof(tmpstr), "Parked at %d", zpc->parked_at);
++                                          pri_suspend_acknowledge(pri->pri, e->suspend_req.call,tmpstr);
++                                          pri->pvts[chanpos]->call = NULL;
++                                          pri->pvts[chanpos]->tei = -1;
++                                          pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
++                                      } else {
++                                          pri_suspend_reject(pri->pri, e->suspend_req.call, "cant park a non-bridge");
++                                          ast_mutex_unlock(&pri->pvts[chanpos]->lock);
++                                          break;
++                                      }
++                                  } else {
++                                      pri_suspend_reject(pri->pri, e->suspend_req.call, "");
++                                  }
++                                  ast_mutex_unlock(&pri->pvts[chanpos]->lock);
++                              }
++                              break;
++                      case PRI_EVENT_RESUME_REQ:
++                              if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
++                                  break;
++                              }
++                              chanpos = pri_find_empty_chan(pri, 1);
++                              if (chanpos < 0) {
++                                      pri_resume_reject(pri->pri, e->resume_req.call,"All channels busy");
++                                      ast_log(LOG_WARNING, "Resume requested on odd channel number %d span %d\n", chanpos, pri->span);
++                                      chanpos = -1;
++                              } else if (!pri->pvts[chanpos]) {
++                                      pri_resume_reject(pri->pri, e->resume_req.call,"General protection fault in module 0x0BRI");
++                                      chanpos = -1;
++                              }
 +
-+      cur=aalot;
-+      while(cur) {
-+              con = ast_context_find(cur->context);
-+              if (!con) {
-+                      con = ast_context_create(NULL,cur->context, registrar);
-+                      if (!con) {
-+                              ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", cur->context);
-+                      }
-+              }
-+              if (con) {
-+                      snprintf(exten, sizeof(exten), "%s", cur->exten);
-+                      snprintf(args, sizeof(args), "%s|%s", cur->context, cur->exten);
-+                      ast_add_extension2(con, 1, exten, 1, NULL, NULL, autoanswer, strdup((char *)args), free, registrar);
-+              }
-+              cur = cur->next;
-+      }
++                              if (chanpos > -1) {
++                                  ast_mutex_lock(&pri->pvts[chanpos]->lock);
++                                  if (!pri->pvts[chanpos]->owner) {
++                                      struct zt_suspended_call *zpc, *zpcl;
++                                      int unparked=0;
++                                      char extenstr[255], temp[255];
++                                      zpc = NULL;
++                                      zpcl = pri->suspended_calls;
++                                      while (zpcl) {
++                                      //    ast_log(LOG_NOTICE, "zpc->parked_at %d zpcl->callid %s\n",zpcl->parked_at, zpcl->callid);
++                                          if (((strlen(zpcl->callid) == 0) && (strlen(e->resume_req.callid)==0)) || (!strcmp(zpcl->callid,e->resume_req.callid))) {
++                                              int law;
++                                              // found a parked call
++                                              snprintf(extenstr, sizeof(extenstr), "%d", zpcl->parked_at);
++                                              strncpy(pri->pvts[chanpos]->exten, extenstr, sizeof(pri->pvts[chanpos]->exten));
++                                      //      strncpy(pri->pvts[chanpos]->context, ast_parking_con(), sizeof(pri->pvts[chanpos]->context));
++                                              pri->pvts[chanpos]->call = e->resume_req.call;
++                                              law = 1;
++                                              if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1)
++                                                  ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]), law);
++                                      // uhh ohh...what shall we do without the bearer cap???
++                                              law = ZT_LAW_ALAW;
++                                              res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
++                                              if (res < 0)
++                                                  ast_log(LOG_WARNING, "Unable to set law on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
++                                              if (!pri->pvts[chanpos]->digital) {
++                                                  res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
++                                              } else {
++                                                  res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[chanpos]->law);
++                                              }
++                                              if (res < 0)
++                                                  ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
++                                              /* Start PBX */
++                                              c = zt_new(pri->pvts[chanpos], AST_STATE_UP, 1, SUB_REAL, law, PRI_TRANS_CAP_SPEECH);
++                                              if (c) {
++                                                  pri->pvts[chanpos]->owner = c;
++                                                  pri->pvts[chanpos]->call = e->resume_req.call;
++                                                  zt_enable_ec(pri->pvts[chanpos]);
++                                                  zt_train_ec(pri->pvts[chanpos]);
++                                              } else {
++                                                  ast_log(LOG_ERROR, "unable to start pbx\n");
++                                              }
 +
-+      ast_mutex_unlock(&autoanswer_lock);
-+}
-+static void *do_autoanswer_thread(void *ignore)
-+{
-+      int ms, tms, max;
-+      struct ast_context *con;
-+      char exten[AST_MAX_EXTENSION];
-+      struct aauser *pu, *pl, *pt = NULL;
-+      struct timeval tv;
-+      struct ast_frame *f;
-+      int x;
-+      fd_set rfds, efds;
-+      fd_set nrfds, nefds;
-+      FD_ZERO(&rfds);
-+      FD_ZERO(&efds);
-+      for (;;) {
-+              ms = -1;
-+              max = -1;
-+              ast_mutex_lock(&autoanswer_lock);
-+              pl = NULL;
-+              pu = aalot;
-+              gettimeofday(&tv, NULL);
-+              FD_ZERO(&nrfds);
-+              FD_ZERO(&nefds);
-+              while(pu) {
-+                      tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
-+                      for (x=0;x<AST_MAX_FDS;x++) {
-+                              if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
-+                                      if (FD_ISSET(pu->chan->fds[x], &efds))
-+                                              ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
-+                                      else
-+                                              ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
-+                                      pu->chan->fdno = x;
-+                                      /* See if they need servicing */
-+                                      f = ast_read(pu->chan);
-+                                      if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass ==  AST_CONTROL_HANGUP))) {
-+                                              /* There's a problem, hang them up*/
-+                                              if (option_verbose > 1) 
-+                                                      ast_verbose(VERBOSE_PREFIX_2 "%s logged out of autoanswer app\n", pu->chan->name);
-+                                              manager_event(EVENT_FLAG_CALL, "AutoanswerLogout",
-+                                                  "Channel: %s\r\n"
-+                                                  "Uniqueid: %s\r\n"
-+                                                  "Context: %s\r\n"
-+                                                  "Exten: %s\r\n"
-+                                              ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
-+                                              ast_hangup(pu->chan);
-+                                              con = ast_context_find(pu->context);
-+                                              if (con) {
-+                                                  snprintf(exten, sizeof(exten), "%s", pu->exten);
-+                                                  if (ast_context_remove_extension2(con, exten, 1, registrar))
-+                                                      ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
++                                              if (zpc) {
++                                                  zpc->next = zpcl->next;
++                                                  free(zpcl);
++                                                  zpcl = zpc->next;
 +                                              } else {
-+                                                      ast_log(LOG_WARNING, "Whoa, no %s context?\n", pu->exten);
++                                                  // remove head
++                                                  pri->suspended_calls = zpcl->next;
++                                                  free(zpcl);
++                                                  zpcl = pri->suspended_calls;
++                                                  zpc = NULL;
 +                                              }
-+                                              /* And take them out of the parking lot */
-+                                              if (pl) 
-+                                                      pl->next = pu->next;
-+                                              else
-+                                                      aalot = pu->next;
-+                                              pt = pu;
-+                                              pu = pu->next;
-+                                              free(pt);
-+                                              break;
++                                              unparked = 1;
++                                              snprintf(temp, sizeof(temp), "Unparked %s", extenstr);
++                                              pri_resume_acknowledge(pri->pri, e->resume_req.call, chanpos + 1, temp);
++                                              break;
++                                          }
++                                          zpc = zpcl;
++                                          if (zpcl) zpcl = zpcl->next;
++                                      }
++                                      if (!unparked)
++                                          pri_resume_reject(pri->pri, e->resume_req.call,"No suspended call to unpark!");
++                                  } else {
++                                      pri_resume_reject(pri->pri, e->resume_req.call,"No suspended call to unpark!");
++                                  }
++                                  ast_mutex_unlock(&pri->pvts[chanpos]->lock);
++                              }
++                              break;
++                      case PRI_EVENT_HOLD_REQ:
++                              if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
++                                  pri_hold_reject(pri->pri, e->hold_req.call);
++                                  break;
++                              }
++                              /* holded calls are not implemented yet */
++                              pri_hold_reject(pri->pri, e->hold_req.call);
++                              break;
++                      case PRI_EVENT_RETRIEVE_REQ:
++                              if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
++                                  pri_retrieve_reject(pri->pri, e->retrieve_req.call);
++                                  break;
++                              }
++                              /* Holded calls are currently not supported */
++                              pri_retrieve_reject(pri->pri, e->retrieve_req.call);
++                              chanpos = -1;
++                              break;
++                      case PRI_EVENT_DISPLAY_RECEIVED:
++                              ast_log(LOG_NOTICE, "DISPLAY IE: [ %s ] received\n",e->display.text);
++                              chanpos = pri_find_principle(pri, e->display.channel);
++                              if (chanpos < 0) {
++                                  ast_log(LOG_WARNING, "odd channel number %d span %d\n", chanpos, pri->span);
++                                  chanpos = -1;
++                              }
++                              if (chanpos > -1) {
++                                  if (pri->pvts[chanpos]->owner) {
++                      //              ast_sendtext(pri->pvt[chanpos]->owner, e->display.text);
++                                  }
++                              }
++                              break;
+                       case PRI_EVENT_ANSWER:
+                               chanpos = pri_find_principle(pri, e->answer.channel);
+                               if (chanpos < 0) {
+@@ -9126,6 +9626,7 @@ static void *pri_dchannel(void *vpri)
+                                                       PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
+                                       } else {
+                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
++                                              pri->pvts[chanpos]->tei = e->answer.tei;
+                                               /* Now we can do call progress detection */
+                                               /* We changed this so it turns on the DSP no matter what... progress or no progress.
+@@ -9155,11 +9656,16 @@ static void *pri_dchannel(void *vpri)
+                                                               ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
+                                                       pri->pvts[chanpos]->dop.dialstr[0] = '\0';
+                                               } else if (pri->pvts[chanpos]->confirmanswer) {
+-                                                      ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
++                                                      ast_log(LOG_DEBUG, "Waiting for answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
++                                                      enable_dtmf_detect(pri->pvts[chanpos]);
+                                               } else {
++                                                      pri->pvts[chanpos]->dialing = 0;
+                                                       pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
+                                                       /* Enable echo cancellation if it's not on already */
+                                                       zt_enable_ec(pri->pvts[chanpos]);
++                                                      zt_train_ec(pri->pvts[chanpos]);
++                                                      /* stop ignoring inband dtmf */
++                                                      enable_dtmf_detect(pri->pvts[chanpos]);
+                                               }
+ #ifdef SUPPORT_USERUSER
+@@ -9216,20 +9722,29 @@ static void *pri_dchannel(void *vpri)
+                                                               ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n", 
+                                                                       pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
+                                               } else {
+-                                                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
++                                                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
+                                                       pri->pvts[chanpos]->call = NULL;
++                                                      pri->pvts[chanpos]->tei = -1;
+                                               }
+                                               if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
+-                                                      if (option_verbose > 2)
++                                                      if ((pri->nodetype != BRI_CPE_PTMP) && (pri->nodetype != BRI_NETWORK_PTMP)) {
++                                                          if (option_verbose > 2)
+                                                               ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 
+-                                                                      PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
+-                                                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
+-                                                      pri->pvts[chanpos]->resetting = 1;
+-                                              }
+-                                              if (e->hangup.aoc_units > -1)
++                                                                      PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
++                                                          pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
++                                                          pri->pvts[chanpos]->resetting = 1;
++                                                      }
++                                              }
++                                              if (e->hangup.aoc_units > -1) {
++                                                      if (pri->pvts[chanpos]->owner) {
++                                                          char tmpstr[256];
++                                                          snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
++                                                          pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
++                                                      }
+                                                       if (option_verbose > 2)
+                                                               ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
+                                                                       pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
++                                              }
+ #ifdef SUPPORT_USERUSER
+                                               if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
+@@ -9242,8 +9757,9 @@ static void *pri_dchannel(void *vpri)
+                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+                                       } else {
+-                                              ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 
+-                                                      PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
++                                              ast_log(LOG_NOTICE, "Hangup, did not find cref %d, tei %d\n",e->hangup.cref, e->hangup.tei);
++                                              ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
++                                                              PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
+                                       }
+                               } 
+                               break;
+@@ -9253,15 +9769,23 @@ static void *pri_dchannel(void *vpri)
+                       case PRI_EVENT_HANGUP_REQ:
+                               chanpos = pri_find_principle(pri, e->hangup.channel);
+                               if (chanpos < 0) {
+-                                      ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 
+-                                              PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
+-                              } else {
++                                      if (pri->nodetype == BRI_NETWORK_PTMP) {
++                                          pri_hangup(pri->pri, e->hangup.call, e->hangup.cause, -1);
 +                                      } else {
-+                                              /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
-+                                              ast_frfree(f);
-+                                              goto std;       /* XXX Ick: jumping into an else statement??? XXX */
++                                          ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
++                                              PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
 +                                      }
-+                              }
-+                      }
-+                      if (x >= AST_MAX_FDS) {
-+std:                          for (x=0;x<AST_MAX_FDS;x++) {
-+                                      /* Keep this one for next one */
-+                                      if (pu->chan->fds[x] > -1) {
-+                                              FD_SET(pu->chan->fds[x], &nrfds);
-+                                              FD_SET(pu->chan->fds[x], &nefds);
-+                                              if (pu->chan->fds[x] > max)
-+                                                      max = pu->chan->fds[x];
++                              } else if ((pri->pvts[chanpos]->priindication_oob != 2) || (!e->hangup.inband_progress) || (!pri->pvts[chanpos]->outgoing)) {
++                                                                  /* dont hang up if we want to hear inband call progress */
+                                       chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
+                                       if (chanpos > -1) {
+                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
+                                               if (pri->pvts[chanpos]->realcall) 
+                                                       pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
+                                               else if (pri->pvts[chanpos]->owner) {
++                                                      char tmpstr[256];
++                                                      snprintf(tmpstr, sizeof(tmpstr), "%d", e->hangup.cause);
++                                                      pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "PRI_CAUSE", tmpstr);
+                                                       pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
+                                                       if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
+                                                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+@@ -9288,16 +9812,34 @@ static void *pri_dchannel(void *vpri)
+                                                               if (option_verbose > 2)
+                                                                       ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
+                                                                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
++                                                      if (e->hangup.aoc_units > -1) {
++                                                          if (pri->pvts[chanpos]->owner) {
++                                                              char tmpstr[256];
++                                                              snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
++                                                              pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
++                                                          }
++                                                          if (option_verbose > 2)
++                                                              ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
++                                                                      pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
++                                                      }
++                                                      if (pri->nodetype == BRI_NETWORK_PTMP) {
++                                                              pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
++                                                              pri->pvts[chanpos]->call = NULL;
++                                                              pri->pvts[chanpos]->tei = -1;
++                                                      }
+                                               } else {
+-                                                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
++                                                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
+                                                       pri->pvts[chanpos]->call = NULL;
++                                                      pri->pvts[chanpos]->tei = -1;
+                                               }
+                                               if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
+-                                                      if (option_verbose > 2)
++                                                      if ((pri->nodetype != BRI_CPE_PTMP) && (pri->nodetype != BRI_NETWORK_PTMP)) {
++                                                          if (option_verbose > 2)
+                                                               ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n", 
+                                                                       PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
+-                                                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
+-                                                      pri->pvts[chanpos]->resetting = 1;
++                                                          pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
++                                                          pri->pvts[chanpos]->resetting = 1;
++                                                      }
+                                               }
+ #ifdef SUPPORT_USERUSER
+@@ -9311,9 +9853,27 @@ static void *pri_dchannel(void *vpri)
+                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+                                       } else {
+-                                              ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
++                                              if (pri->nodetype != BRI_NETWORK_PTMP) {
++                                                  ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
++                                              } else {
++                                                      ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
++                                              }
+                                       }
+                               } 
++                              if ((chanpos > -1) && (pri->pvts[chanpos]->owner) && (pri->pvts[chanpos]->priindication_oob == 2) && (e->hangup.inband_progress) && (pri->pvts[chanpos]->outgoing)) {
++                                  ast_mutex_lock(&pri->pvts[chanpos]->lock);
++                                      if (e->hangup.aoc_units > -1) {
++                                          char tmpstr[256];
++                                          snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
++                                          pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
++                                          if (option_verbose > 2)
++                                              ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
++                                                  pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
 +                                      }
++                                      pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
++                                      ast_channel_setwhentohangup(pri->pvts[chanpos]->owner, 5);
++                                  ast_mutex_unlock(&pri->pvts[chanpos]->lock);
 +                              }
-+                              /* Keep track of our longest wait */
-+                              if ((tms < ms) || (ms < 0))
-+                                      ms = tms;
-+                              pl = pu;
-+                              pu = pu->next;
-+                      }
-+              }
-+              ast_mutex_unlock(&autoanswer_lock);
-+              rfds = nrfds;
-+              efds = nefds;
-+              tv.tv_sec = ms / 1000;
-+              tv.tv_usec = (ms % 1000) * 1000;
-+              /* Wait for something to happen */
-+              ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
-+              pthread_testcancel();
-+      }
-+      return NULL;    /* Never reached */
-+}
-+
-+static int autoanswer_exec(struct ast_channel *chan, void *data)
-+{
-+      int res=0;
-+      struct ast_channel *peer=NULL;
-+      struct aauser *pu, *pl=NULL;
-+      struct ast_bridge_config config;
-+      char *s, *stringp, *aacontext, *aaexten = NULL;
-+      char datastring[80];
-+      struct ast_module_user *u;
-+
-+
-+      if (!data) {
-+              ast_log(LOG_WARNING, "Autoanswer requires an argument (extension number)\n");
-+              return -1;
-+      }
-+      s = ast_strdupa((void *) data);
-+      stringp=s;
-+      aacontext = strsep(&stringp, "|");
-+      aaexten = strsep(&stringp, "|");
-+      if (!aaexten) {
-+          aaexten = aacontext;
-+          aacontext = NULL;
-+      }
-+      if (!aaexten) {
-+              ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
-+              return -1;
-+      } else {
-+              if (!aacontext) {
-+                      aacontext = "default";
-+              }
-+      }
-+
-+      u = ast_module_user_add(chan);
-+      ast_mutex_lock(&autoanswer_lock);
-+      pu = aalot;
-+      while(pu) {
-+              if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
-+                      if (pl)
-+                              pl->next = pu->next;
-+                      else
-+                              aalot = pu->next;
-+                      break;
-+              }
-+              pl = pu;
-+              pu = pu->next;
-+      }
-+      ast_mutex_unlock(&autoanswer_lock);
-+      if (pu) {
-+              peer = pu->chan;
-+              free(pu);
-+              pu = NULL;
-+      }
-+      /* JK02: it helps to answer the channel if not already up */
-+      if (chan->_state != AST_STATE_UP) {
-+              ast_answer(chan);
-+      }
-+
-+      if (peer) {
-+              ast_moh_stop(peer);
-+              /* Play a courtesy beep in the callED channel to prefix the bridge connecting */        
-+              if (!ast_strlen_zero(courtesytone)) {
-+                      if (!ast_streamfile(peer, courtesytone, peer->language)) {
-+                              if (ast_waitstream(peer, "") < 0) {
-+                                      ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
-+                                      ast_hangup(peer);
-+                                      return -1;
-+                              }
-+                      }
-+              }
-+ 
-+              res = ast_channel_make_compatible(chan, peer);
-+              if (res < 0) {
-+                      ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
-+                      ast_hangup(peer);
-+                      return -1;
-+              }
-+              /* This runs sorta backwards, since we give the incoming channel control, as if it
-+                 were the person called. */
-+              if (option_verbose > 2) 
-+                      ast_verbose(VERBOSE_PREFIX_3 "Channel %s autoanswered  %s\n", peer->name, chan->name);
-+              manager_event(EVENT_FLAG_CALL, "Autoanswer",
-+                    "Channel: %s\r\n"
-+                    "Uniqueid: %s\r\n"
-+                    "Channel2: %s\r\n"
-+                    "Uniqueid2: %s\r\n"
-+                    "Context: %s\r\n"
-+                    "Exten: %s\r\n"
-+                ,chan->name, chan->uniqueid, peer->name, peer->uniqueid, aacontext, aaexten);
-+
-+
-+              memset(&config,0,sizeof(struct ast_bridge_config));
-+              ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
-+              ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
-+              config.timelimit = 0;
-+              config.play_warning = 0;
-+              config.warning_freq = 0;
-+              config.warning_sound=NULL;
-+              res = ast_bridge_call(chan,peer,&config);
-+
-+              if (option_verbose > 2) 
-+                      ast_verbose(VERBOSE_PREFIX_3 "returning from bridge %s\n", peer->name);
-+                      /* relogin */
-+              snprintf(datastring, sizeof(datastring) - 1, "%s|%s", aacontext, aaexten);
-+              ast_autoanswer_login(peer, datastring);
-+              return res;
-+      } else {
-+              if (option_verbose > 2) 
-+                      ast_verbose(VERBOSE_PREFIX_3 "Nobody logged in for autoanswer %s@%s\n", aaexten, aacontext);
-+              res = -1;
-+      }
-+      ast_module_user_remove(u);
-+      return res;
-+}
+                               break;
+                       case PRI_EVENT_HANGUP_ACK:
+                               chanpos = pri_find_principle(pri, e->hangup.channel);
+@@ -9325,6 +9885,7 @@ static void *pri_dchannel(void *vpri)
+                                       if (chanpos > -1) {
+                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
+                                               pri->pvts[chanpos]->call = NULL;
++                                              pri->pvts[chanpos]->tei = -1;
+                                               pri->pvts[chanpos]->resetting = 0;
+                                               if (pri->pvts[chanpos]->owner) {
+                                                       if (option_verbose > 2) 
+@@ -9431,10 +9992,22 @@ static void *pri_dchannel(void *vpri)
+                                       ast_mutex_lock(&pri->pvts[chanpos]->lock);
+                                       switch (e->notify.info) {
+                                       case PRI_NOTIFY_REMOTE_HOLD:
++                                              if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
++                                                  ast_log(LOG_DEBUG, "Received REMOTE_HOLD notification on NETWORK channel. Starting MoH\n");
++                                                  ast_moh_start(ast_bridged_channel(pri->pvts[chanpos]->owner), NULL, pri->pvts[chanpos]->mohinterpret);
++                                              } else {
++                                                  ast_log(LOG_DEBUG, "Received REMOTE_HOLD notification on CPE channel. Not Starting MoH\n");
++                                              }
+                                               f.subclass = AST_CONTROL_HOLD;
+                                               zap_queue_frame(pri->pvts[chanpos], &f, pri);
+                                               break;
+                                       case PRI_NOTIFY_REMOTE_RETRIEVAL:
++                                              if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
++                                                  ast_log(LOG_DEBUG, "Received REMOTE_RETRIEVAL notification on NETWORK channel. Stopping MoH\n");
++                                                  ast_moh_stop(ast_bridged_channel(pri->pvts[chanpos]->owner));
++                                              } else {
++                                                  ast_log(LOG_DEBUG, "Received REMOTE_RETRIEVAL notification on CPE channel.\n");
++                                              }
+                                               f.subclass = AST_CONTROL_UNHOLD;
+                                               zap_queue_frame(pri->pvts[chanpos], &f, pri);
+                                               break;
+@@ -9442,6 +10015,23 @@ static void *pri_dchannel(void *vpri)
+                                       ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+                               }
+                               break;
++                      case PRI_EVENT_FACILITY:
++                                  if (e->facility.operation == 0x0D) {
++                                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
 +
++                                      ast_log(LOG_NOTICE, "call deflection to %s requested.\n", e->facility.forwardnum);
++                                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
++                                          /* transfer */
++                                          if (owner) {
++                                              ast_string_field_build(owner, call_forward, 
++                                                              "Local/%s@%s",  e->facility.forwardnum,
++                                                              owner->context);
++                                          }
++                                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
++                                  } else {
++                                      ast_log(LOG_WARNING, "Unknown facility operation %#x requested.\n", e->facility.operation);
++                                  }
++                              break;
+                       default:
+                               ast_log(LOG_DEBUG, "Event: %d\n", e->e);
+                       }
+@@ -9503,7 +10093,7 @@ static int start_pri(struct zt_pri *pri)
+                       pri->fds[i] = -1;
+                       return -1;
+               }
+-              pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
++              pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype, pri->span);
+               /* Force overlap dial if we're doing GR-303! */
+               if (pri->switchtype == PRI_SWITCH_GR303_TMC)
+                       pri->overlapdial = 1;
+@@ -9571,39 +10161,77 @@ static char *complete_span_5(const char 
  
- int ast_pickup_call(struct ast_channel *chan)
- {
-@@ -2419,6 +2877,7 @@ static int load_config(void) 
- static int reload(void)
+ static int handle_pri_set_debug_file(int fd, int argc, char **argv)
  {
-+      autoanswer_reregister_extensions();
-       return load_config();
- }
-@@ -2442,6 +2901,12 @@ static int load_module(void)
-                       "Park a channel", mandescr_park); 
-       }
-+      ast_pthread_create(&autoanswer_thread, NULL, do_autoanswer_thread, NULL);
-+      if (!res)
-+              res |= ast_register_application(autoanswerlogin, autoanswer_login_exec, synopsis3, descrip3);
-+      if (!res)
-+              res |= ast_register_application(autoanswer, autoanswer_exec, synopsis4, descrip4);
-+
-       res |= ast_devstate_prov_add("Park", metermaidstate);
-       return res;
-@@ -2456,6 +2921,8 @@ static int unload_module(void)
-       ast_manager_unregister("Park");
-       ast_cli_unregister_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
-       ast_unregister_application(parkcall);
-+      ast_unregister_application(autoanswer);
-+      ast_unregister_application(autoanswerlogin);
-       ast_devstate_prov_del("Park");
-       return ast_unregister_application(parkedcall);
- }
---- a/include/asterisk/features.h
-+++ b/include/asterisk/features.h
-@@ -72,6 +72,12 @@ int ast_park_call(struct ast_channel *ch
- */
- int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *host, int timeout, int *extout);
-+extern int ast_hold_call(struct ast_channel *chan, struct ast_channel *host);
-+extern int ast_masq_hold_call(struct ast_channel *rchan, struct ast_channel *host);
-+extern int ast_retrieve_call(struct ast_channel *chan, char *uniqueid);
-+extern int ast_retrieve_call_to_death(char *uniqueid);
-+extern struct ast_channel *ast_get_holded_call(char *uniqueid);
+-      int myfd;
++      int myfd, x, d;
++      int span;
 +
- /*! \brief Determine system parking extension
-  *  Returns the call parking extension for drivers that provide special
-     call parking help */
---- a/res/res_features.c
-+++ b/res/res_features.c
-@@ -62,6 +62,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revisi
- #include "asterisk/adsi.h"
- #include "asterisk/devicestate.h"
- #include "asterisk/monitor.h"
-+#include "asterisk/indications.h"
- #define DEFAULT_PARK_TIME 45000
- #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
-@@ -80,6 +81,7 @@ enum {
- };
++      if (argc < 6)
++              return RESULT_SHOWUSAGE;
  
- static char *parkedcall = "ParkedCall";
-+static char *holdedcall = "HoldedCall";
+       if (!strncasecmp(argv[1], "set", 3)) {
+-              if (argc < 5) 
++              if (argc < 7)
+                       return RESULT_SHOWUSAGE;
  
- static int parkaddhints = 0;                               /*!< Add parking hints automatically */
- static int parkingtime = DEFAULT_PARK_TIME;                /*!< No more than 45 seconds parked before you do something with them */
-@@ -164,6 +166,22 @@ struct parkeduser {
-       struct parkeduser *next;
- };
+-              if (ast_strlen_zero(argv[4]))
++              if (!argv[4] || ast_strlen_zero(argv[4]))
+                       return RESULT_SHOWUSAGE;
  
-+struct holdeduser {
-+      struct ast_channel *chan;
-+      struct timeval start;
-+      int parkingnum;
-+      int cref;
-+      int tei;
-+      /* Where to go if our parking time expires */
-+      char context[AST_MAX_EXTENSION];
-+      char exten[AST_MAX_EXTENSION];
-+      int priority;
-+      int parkingtime;
-+      char uniqueid[AST_MAX_UNIQUEID];
-+      char uniqueidpeer[AST_MAX_UNIQUEID];
-+      struct holdeduser *next;
-+};
++              if (!argv[5])
++                      return RESULT_SHOWUSAGE;
 +
- /* auto answer user */
- struct aauser {
-       struct ast_channel *chan;
-@@ -183,10 +201,16 @@ static pthread_t autoanswer_thread;
- static struct parkeduser *parkinglot;
-+static struct holdeduser *holdlist;
++              if (!argv[6] || ast_strlen_zero(argv[6]))
++                      return RESULT_SHOWUSAGE;
 +
- AST_MUTEX_DEFINE_STATIC(parking_lock);        /*!< protects all static variables above */
-+AST_MUTEX_DEFINE_STATIC(holding_lock);
++              span = atoi(argv[6]);
++              if ((span < 1) && (span > NUM_SPANS)) {
++                      return RESULT_SUCCESS;
++              }
 +
- static pthread_t parking_thread;
-+static pthread_t holding_thread;
 +
- char *ast_parking_ext(void)
- {
-       return parking_ext;
-@@ -2011,6 +2035,282 @@ static int park_exec(struct ast_channel 
-       return res;
- }
+               myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
+               if (myfd < 0) {
+                       ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
+                       return RESULT_SUCCESS;
+               }
++              for (x=0; x < NUM_SPANS; x++) {
++                  ast_mutex_lock(&pris[x].lock);
  
-+int ast_hold_call(struct ast_channel *chan, struct ast_channel *peer)
-+{
-+      /* We put the user in the parking list, then wake up the parking thread to be sure it looks
-+         after these channels too */
-+      struct holdeduser *pu;
-+      pu = malloc(sizeof(struct holdeduser));
-+      if (pu) {
-+              memset(pu, 0, sizeof(pu));
-+              ast_mutex_lock(&holding_lock);
-+              chan->appl = "Holded Call";
-+              chan->data = NULL; 
-+
-+              pu->chan = chan;
-+              strncpy(pu->uniqueid, chan->uniqueid, sizeof(pu->uniqueid));
-+              strncpy(pu->uniqueidpeer, peer->uniqueid, sizeof(pu->uniqueidpeer));
-+              /* Start music on hold */
-+              ast_moh_start(pu->chan, NULL, NULL);
-+              gettimeofday(&pu->start, NULL);
-+              pu->next = holdlist;
-+              holdlist = pu;
-+              ast_mutex_unlock(&holding_lock);
-+              /* Wake up the (presumably select()ing) thread */
-+              pthread_kill(holding_thread, SIGURG);
+-              ast_mutex_lock(&pridebugfdlock);
+-
+-              if (pridebugfd >= 0)
+-                      close(pridebugfd);
+-
+-              pridebugfd = myfd;
+-              ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
+-              
+-              ast_mutex_unlock(&pridebugfdlock);
++                  if (pris[x].span == span) {
++                      if (pris[x].debugfd >= 0)
++                          close(pris[x].debugfd);
++                      pris[x].debugfd = myfd;
++                      for (d=0; d < NUM_DCHANS; d++) {
++                          if (pris[x].dchans[d])
++                              pri_set_debug_fd(pris[x].dchans[d], myfd);
++                      }
++                  }
++                  ast_mutex_unlock(&pris[x].lock);
++              }
+-              ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
++              ast_cli(fd, "PRI debug output for span %d will be sent to '%s'\n", span, argv[4]);
+       } else {
++              if (!argv[5] || ast_strlen_zero(argv[5]))
++                      return RESULT_SHOWUSAGE;
+               /* Assume it is unset */
+-              ast_mutex_lock(&pridebugfdlock);
+-              close(pridebugfd);
+-              pridebugfd = -1;
+-              ast_cli(fd, "PRI debug output to file disabled\n");
+-              ast_mutex_unlock(&pridebugfdlock);
++              span = atoi(argv[5]);
++              if ((span < 1) && (span > NUM_SPANS)) {
++                      return RESULT_SUCCESS;
++              }
 +
-+              manager_event(EVENT_FLAG_CALL, "HoldedCall",
-+                         "Channel1: %s\r\n"
-+                         "Channel2: %s\r\n"
-+                          "Uniqueid1: %s\r\n"
-+                          "Uniqueid2: %s\r\n"
-+                             ,pu->chan->name, peer->name, pu->chan->uniqueid, peer->uniqueid);
++              for (x=0; x < NUM_SPANS; x++) {
++                  ast_mutex_lock(&pris[x].lock);
 +
-+      } else {
-+              ast_log(LOG_WARNING, "Out of memory\n");
-+              return -1;
-+      }
-+      return 0;
-+}
++                  if (pris[x].span == span) {
++                      if (pris[x].debugfd >= 0)
++                          close(pris[x].debugfd);
++                      pris[x].debugfd = -1;
++                      for (d=0; d < NUM_DCHANS; d++) {
++                          if (pris[x].dchans[d])
++                              pri_set_debug_fd(pris[x].dchans[d], -1);
++                      }
++                  }
++                  ast_mutex_unlock(&pris[x].lock);
++              }
 +
-+int ast_masq_hold_call(struct ast_channel *rchan, struct ast_channel *peer)
-+{
-+      struct ast_channel *chan;
-+      struct ast_frame *f;
-+      /* Make a new, fake channel that we'll use to masquerade in the real one */
-+      chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Onhold/%s",rchan->name);
-+      if (chan) {
-+              /* Let us keep track of the channel name */
-+              ast_string_field_build(chan, name, "Onhold/%s",rchan->name);
-+              /* Make formats okay */
-+              chan->readformat = rchan->readformat;
-+              chan->writeformat = rchan->writeformat;
-+              ast_channel_masquerade(chan, rchan);
-+              /* Setup the extensions and such */
-+              strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
-+              strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
-+              chan->priority = rchan->priority;
-+              /* this might be dirty, but we need to preserve the uniqueid */
-+              ast_string_field_build(chan, uniqueid, "%s",rchan->uniqueid);
-+              /* Make the masq execute */
-+              f = ast_read(chan);
-+              if (f)
-+                      ast_frfree(f);
-+              ast_hold_call(chan, peer);
-+              return -1;
-+      } else {
-+              ast_log(LOG_WARNING, "Unable to create holded channel\n");
-+              return -1;
-+      }
-+      return 0;
-+}
++              ast_cli(fd, "PRI debug output to file for span %d disabled\n", span);
+       }
+       return RESULT_SUCCESS;
+@@ -9644,6 +10272,7 @@ static int handle_pri_debug(int fd, int 
 +
-+int ast_retrieve_call(struct ast_channel *chan, char *uniqueid)
-+{
-+      int res=-1, dres=-1;
-+      struct ast_channel *peer=NULL;
-+      struct ast_bridge_config config;
+ static int handle_pri_no_debug(int fd, int argc, char *argv[])
+ {
+       int span;
+@@ -9793,10 +10422,6 @@ static int handle_pri_show_debug(int fd,
+               }
+       }
+-      ast_mutex_lock(&pridebugfdlock);
+-      if (pridebugfd >= 0) 
+-              ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
+-      ast_mutex_unlock(&pridebugfdlock);
+           
+       if (!count) 
+               ast_cli(fd, "No debug set or no PRI running\n");
+@@ -9823,6 +10448,18 @@ static const char pri_show_spans_help[] 
+       "Usage: pri show spans\n"
+       "       Displays PRI Information\n";
++static char bri_debug_help[] =
++      "Usage: bri debug span <span>\n"
++      "       Enables debugging on a given BRI span\n";
 +
-+      peer = ast_get_holded_call(uniqueid);
++static char bri_no_debug_help[] =
++      "Usage: bri no debug span <span>\n"
++      "       Disables debugging on a given BRI span\n";
 +
-+      /* JK02: it helps to answer the channel if not already up */
-+      if (chan->_state != AST_STATE_UP) {
-+              ast_answer(chan);
-+      }
++static char bri_really_debug_help[] =
++      "Usage: bri intensive debug span <span>\n"
++      "       Enables debugging down to the Q.921 level\n";
 +
-+      if (peer) {
-+              ast_mutex_unlock(&peer->lock);
-+              ast_moh_stop(peer);
-+              res = ast_channel_make_compatible(chan, peer);
-+              if (res < 0) {
-+                      ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
-+                      ast_hangup(peer);
-+                      return -1;
-+              }
-+              /* This runs sorta backwards, since we give the incoming channel control, as if it
-+                 were the person called. */
-+              if (option_verbose > 2) 
-+                      ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to holded call %s\n", chan->name, peer->name);
+ static struct ast_cli_entry zap_pri_cli[] = {
+       { { "pri", "debug", "span", NULL },
+       handle_pri_debug, "Enables PRI debugging on a span",
+@@ -9847,6 +10484,15 @@ static struct ast_cli_entry zap_pri_cli[
+       { { "pri", "show", "debug", NULL },
+       handle_pri_show_debug, "Displays current PRI debug settings" },
++      { { "bri", "debug", "span", NULL }, handle_pri_debug,
++        "Enables BRI debugging on a span", bri_debug_help, complete_span_4 },
 +
-+              memset(&config,0,sizeof(struct ast_bridge_config));
-+              ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
-+              ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
-+              config.timelimit = 0;
-+              config.play_warning = 0;
-+              config.warning_freq = 0;
-+              config.warning_sound=NULL;
-+              res = ast_bridge_call(chan,peer,&config);
++      { { "bri", "no", "debug", "span", NULL }, handle_pri_no_debug,
++        "Disables BRI debugging on a span", bri_no_debug_help, complete_span_5 },
 +
-+              /* Simulate the PBX hanging up */
-+              if (res != AST_PBX_NO_HANGUP_PEER)
-+                      ast_hangup(peer);
-+              return res;
-+      } else {
-+              /* XXX Play a message XXX */
-+        dres = ast_streamfile(chan, "pbx-invalidpark", chan->language);
-+        if (!dres)
-+          dres = ast_waitstream(chan, "");
-+        else {
-+          ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
-+          dres = 0;
-+        }
-+      }
-+      return res;
-+}
++      { { "bri", "intense", "debug", "span", NULL }, handle_pri_really_debug,
++        "Enables REALLY INTENSE BRI debugging", bri_really_debug_help, complete_span_5 },
 +
-+int ast_retrieve_call_to_death(char *uniqueid)
+       { { "pri", "set", "debug", "file", NULL },
+       handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
+@@ -9859,8 +10505,76 @@ static struct ast_cli_entry zap_pri_cli[
+ #endif
+ };
++static char *zapCD_tdesc = "Call Deflection";
++static char *zapCD_app = "zapCD";
++static char *zapCD_synopsis = "Call Deflection";
++
++static int app_zapCD(struct ast_channel *chan, void *data)
 +{
-+      int res=-1;
-+      struct ast_channel *peer=NULL;
++ struct zt_pvt *p = chan->tech_pvt;
 +
-+      peer = ast_get_holded_call(uniqueid);
++ if((!p->pri) || (!p->pri->pri)) {
++      return -1;
++ }
 +
-+      if (peer) {
-+              res=0;
-+              if (option_verbose > 2) 
-+                      ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
-+              ast_mutex_unlock(&peer->lock);
-+              ast_hangup(peer);
-+      } else {
-+              ast_log(LOG_WARNING, "Could not find channel with uniqueid %s to retrieve.\n", uniqueid);
-+      }
-+      return res;
++ if(!data) {
++     ast_log(LOG_WARNING, "zapCD wants a number to deflect to\n");
++      return -1;
++ }
++ return pri_deflect(p->pri->pri, p->call, data);
 +}
 +
-+struct ast_channel *ast_get_holded_call(char *uniqueid)
++static char *zapInband_tdesc = "Inband Call Progress (pre-answer)";
++static char *zapInband_app = "zapInband";
++static char *zapInband_synopsis = "Inband Call Progress";
++
++static int app_zapInband(struct ast_channel *chan, void *data)
 +{
-+      int res=-1;
-+      struct ast_channel *peer=NULL;
-+      struct holdeduser *pu, *pl=NULL;
++ struct zt_pvt *p = chan->tech_pvt;
 +
-+      ast_mutex_lock(&holding_lock);
-+      pu = holdlist;
-+      while(pu) {
-+              if (!strncmp(uniqueid,pu->uniqueid,sizeof(pu->uniqueid))) {
-+                      if (pl)
-+                              pl->next = pu->next;
-+                      else
-+                              holdlist = pu->next; 
-+                      break;
-+              }
-+              pl = pu;
-+              pu = pu->next;
-+      }
-+      ast_mutex_unlock(&holding_lock);
-+      if (pu) {
-+              peer = ast_get_channel_by_uniqueid_locked(pu->uniqueid);
-+              free(pu);
-+              if (peer) {
-+                  res=0;
-+                  if (option_verbose > 2) 
-+                      ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
-+                  ast_moh_stop(peer);
-+                  return peer;
-+              } else {
-+                  if (option_verbose > 2) 
-+                      ast_verbose(VERBOSE_PREFIX_3 "Could not find channel with uniqueid %s.\n", uniqueid);
-+                  return NULL;
-+              }
-+      } else {
-+              ast_log(LOG_WARNING, "Could not find held channel with uniqueid %s to retrieve.\n", uniqueid);
-+      }
-+      return NULL;
++ return pri_acknowledge(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1);
 +}
 +
-+/* this is our autmagically service thread that keeps channels onhold happy */
-+static void *do_holding_thread(void *ignore)
+ #endif /* HAVE_PRI */
++static int app_zapEC(struct ast_channel *chan, void *data)
 +{
-+      int ms, tms, max;
-+      struct holdeduser *pu, *pl, *pt = NULL;
-+      struct timeval tv;
-+      struct ast_frame *f;
-+      int x;
-+      fd_set rfds, efds;
-+      fd_set nrfds, nefds;
-+      FD_ZERO(&rfds);
-+      FD_ZERO(&efds);
-+      for (;;) {
-+              ms = -1;
-+              max = -1;
-+              ast_mutex_lock(&holding_lock);
-+              pl = NULL;
-+              pu = holdlist;
-+              gettimeofday(&tv, NULL);
-+              FD_ZERO(&nrfds);
-+              FD_ZERO(&nefds);
-+              while(pu) {
-+                      tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
-+                              for (x=0;x<AST_MAX_FDS;x++) {
-+                                      if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
-+                                              if (FD_ISSET(pu->chan->fds[x], &efds))
-+                                                      ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
-+                                              else
-+                                                      ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
-+                                              pu->chan->fdno = x;
-+                                              /* See if they need servicing */
-+                                              f = ast_read(pu->chan);
-+                                              if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass ==  AST_CONTROL_HANGUP))) {
-+                                                      /* There's a problem, hang them up*/
-+                                                      if (option_verbose > 1) 
-+                                                              ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being onhold\n", pu->chan->name);
-+                                                      ast_hangup(pu->chan);
-+                                                      /* find the corresponding channel and hang them up too! */
-+                                                      /* but only if it is not bridged yet! */
-+                                                      /* And take them out of the parking lot */
-+                                                      if (pl) 
-+                                                              pl->next = pu->next;
-+                                                      else
-+                                                              holdlist = pu->next;
-+                                                      pt = pu;
-+                                                      pu = pu->next;
-+                                                      free(pt);
-+                                                      break;
-+                                              } else {
-+                                                      /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
-+                                                      ast_frfree(f);
-+                                                      goto std;       /* XXX Ick: jumping into an else statement??? XXX */
-+                                              }
-+                                      }
-+                              }
-+                              if (x >= AST_MAX_FDS) {
-+std:                                  for (x=0;x<AST_MAX_FDS;x++) {
-+                                              /* Keep this one for next one */
-+                                              if (pu->chan->fds[x] > -1) {
-+                                                      FD_SET(pu->chan->fds[x], &nrfds);
-+                                                      FD_SET(pu->chan->fds[x], &nefds);
-+                                                      if (pu->chan->fds[x] > max)
-+                                                              max = pu->chan->fds[x];
-+                                              }
-+                                      }
-+                                      /* Keep track of our longest wait */
-+                                      if ((tms < ms) || (ms < 0))
-+                                              ms = tms;
-+                                      pl = pu;
-+                                      pu = pu->next;
-+                              }
-+              }
-+              ast_mutex_unlock(&holding_lock);
-+              rfds = nrfds;
-+              efds = nefds;
-+              tv.tv_sec = ms / 1000;
-+              tv.tv_usec = (ms % 1000) * 1000;
-+              /* Wait for something to happen */
-+              ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
-+              pthread_testcancel();
++ int res=-1;
++ struct zt_pvt *p = NULL;
++
++ if (!data) {
++      ast_log(LOG_WARNING, "zapEC requires one argument (on | off)\n");
++ }
++ if (chan && !strcasecmp("ZAP",chan->tech->type)) {
++      p = chan->tech_pvt;
++      if (!p) return res;
++      if (!strcasecmp("on",(char *)data)) {
++          zt_enable_ec(p);
++          res = 0;
++          if (option_verbose > 3) {
++              ast_verbose(VERBOSE_PREFIX_3 "Enabled echo cancelation on channel %s.\n", chan->name);
++          }
++      } else if (!strcasecmp("off",(char *)data)) {
++          zt_disable_ec(p);
++          res = 0;
++          if (option_verbose > 3) {
++              ast_verbose(VERBOSE_PREFIX_3 "Disabled echo cancelation on channel %s.\n", chan->name);
++          }
++      } else {
++          ast_log(LOG_WARNING, "Unknown argument %s to zapEC\n", (char *)data);
 +      }
-+      return NULL;    /* Never reached */
-+}
++ } else {
++  ast_log(LOG_WARNING, "zapNoEC only works on ZAP channels, check your extensions.conf!\n");
++  res = 0;
++ }
 +
-+static int retrieve_call_exec(struct ast_channel *chan, void *data) {
-+      int res=0;
-+      struct ast_module_user *u;
-+      char *uniqueid = (char *)data;
-+      u = ast_module_user_add(chan);
-+          res = ast_retrieve_call(chan, uniqueid);
-+      ast_module_user_remove(u);
-+      return res;
++ return res;
 +}
 +
- static int handle_showfeatures(int fd, int argc, char *argv[])
++static char *zapEC_tdesc = "Enable/disable Echo cancelation";
++static char *zapEC_app = "zapEC";
++static char *zapEC_synopsis = "Enable/Disable Echo Cancelation on a Zap channel";
++
+ static int zap_destroy_channel(int fd, int argc, char **argv)
  {
-       int i;
-@@ -2892,6 +3192,7 @@ static int load_module(void)
-               return res;
-       ast_cli_register_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
-       ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
-+      ast_pthread_create(&holding_thread, NULL, do_holding_thread, NULL);
-       res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
-       if (!res)
-               res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
-@@ -2901,6 +3202,7 @@ static int load_module(void)
-                       "Park a channel", mandescr_park); 
+       int channel;
+@@ -10441,8 +11155,11 @@ static int __unload_module(void)
        }
-+      res |= ast_register_application(holdedcall, retrieve_call_exec, synopsis, descrip);
-       ast_pthread_create(&autoanswer_thread, NULL, do_autoanswer_thread, NULL);
-       if (!res)
-               res |= ast_register_application(autoanswerlogin, autoanswer_login_exec, synopsis3, descrip3);
-@@ -2923,6 +3225,7 @@ static int unload_module(void)
-       ast_unregister_application(parkcall);
-       ast_unregister_application(autoanswer);
-       ast_unregister_application(autoanswerlogin);
-+      ast_unregister_application(holdedcall);
-       ast_devstate_prov_del("Park");
-       return ast_unregister_application(parkedcall);
- }
---- a/include/asterisk/channel.h
-+++ b/include/asterisk/channel.h
-@@ -423,6 +423,7 @@ struct ast_channel {
-       unsigned int flags;                             /*!< channel flags of AST_FLAG_ type */
-       unsigned short transfercapability;              /*!< ISDN Transfer Capbility - AST_FLAG_DIGITAL is not enough */
-       AST_LIST_HEAD_NOLOCK(, ast_frame) readq;
-+      char lowlayercompat[16];                        /*!< ISDN Low Layer Compatibility */
-       int alertpipe[2];
-       int nativeformats;                              /*!< Kinds of data this channel can natively handle */
---- a/main/pbx.c
-+++ b/main/pbx.c
-@@ -5132,7 +5132,7 @@ struct app_tmp {
- };
- /*! \brief run the application and free the descriptor once done */
--static void *ast_pbx_run_app(void *data)
-+void *ast_pbx_run_app(void *data)
- {
-       struct app_tmp *tmp = data;
-       struct ast_app *app;
---- a/include/asterisk/pbx.h
-+++ b/include/asterisk/pbx.h
-@@ -145,6 +145,8 @@ void ast_unregister_switch(struct ast_sw
-  */
- struct ast_app *pbx_findapp(const char *app);
-+void *ast_pbx_run_app(void *data);
-+
- /*!
-  * \brief Execute an application
-  *
---- a/channels/chan_zap.c
-+++ b/channels/chan_zap.c
-@@ -11,6 +11,10 @@
-  * the project provides a web site, mailing lists and IRC
-  * channels for your use.
-  *
-+ * Copyright (C) 2003-2006 Junghanns.NET GmbH
-+ * Klaus-Peter Junghanns <kpj@junghanns.net>
-+ *
-+ *
-  * This program is free software, distributed under the terms of
-  * the GNU General Public License Version 2. See the LICENSE file
-  * at the top of the source tree.
-@@ -192,7 +196,7 @@ static const char config[] = "zapata.con
- #define SIG_GR303FXOKS        (0x0100000 | ZT_SIG_FXOKS)
- #define SIG_GR303FXSKS        (0x0100000 | ZT_SIG_FXSKS)
--#define NUM_SPANS             32
-+#define NUM_SPANS             128     /*!<"32 spans", muahahaha, us alaws like to have some more... */
- #define NUM_DCHANS            4       /*!< No more than 4 d-channels */
- #define MAX_CHANNELS  672             /*!< No more than a DS3 per trunk group */
-@@ -218,8 +222,6 @@ static struct ast_channel inuse;
- #ifdef PRI_GETSET_TIMERS
- static int pritimers[PRI_MAX_TIMERS];
+       ast_cli_unregister_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(struct ast_cli_entry));
+       ast_unregister_application(zap_send_keypad_facility_app);
++      ast_unregister_application(zapCD_app);
++      ast_unregister_application(zapInband_app);
  #endif
--static int pridebugfd = -1;
--static char pridebugfilename[1024] = "";
+       ast_cli_unregister_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
++      ast_unregister_application(zapEC_app);
+       ast_manager_unregister( "ZapDialOffhook" );
+       ast_manager_unregister( "ZapHangup" );
+       ast_manager_unregister( "ZapTransfer" );
+@@ -10944,6 +11661,22 @@ static int process_zap(struct zt_chan_co
+                                       confp->chan.sig = SIG_GR303FXSKS;
+                                       confp->chan.radio = 0;
+                                       confp->pri.nodetype = PRI_CPE;
++                              } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
++                                      confp->chan.radio = 0;
++                                      confp->chan.sig = SIG_PRI;
++                                      confp->pri.nodetype = BRI_NETWORK_PTMP;
++                              } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
++                                      confp->chan.sig = SIG_PRI;
++                                      confp->chan.radio = 0;
++                                      confp->pri.nodetype = BRI_CPE_PTMP;
++                              } else if (!strcasecmp(v->value, "bri_net")) {
++                                      confp->chan.radio = 0;
++                                      confp->chan.sig = SIG_PRI;
++                                      confp->pri.nodetype = BRI_NETWORK;
++                              } else if (!strcasecmp(v->value, "bri_cpe")) {
++                                      confp->chan.sig = SIG_PRI;
++                                      confp->chan.radio = 0;
++                                      confp->pri.nodetype = BRI_CPE;
  #endif
+                               } else {
+                                       ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
+@@ -11056,9 +11789,21 @@ static int process_zap(struct zt_chan_co
+                                       confp->chan.priindication_oob = 1;
+                               else if (!strcasecmp(v->value, "inband"))
+                                       confp->chan.priindication_oob = 0;
++                              else if (!strcasecmp(v->value, "passthrough"))
++                                      confp->chan.priindication_oob = 2;
+                               else
+-                                      ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
++                                      ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband', 'outofband' or 'passthrough' at line %d\n",
+                                               v->value, v->lineno);
++                      } else if (!strcasecmp(v->name, "pritransfer")) {
++                              if (!strcasecmp(v->value, "no"))
++                                      confp->chan.pritransfer = 0;
++                              else if (!strcasecmp(v->value, "ect"))
++                                      confp->chan.pritransfer = 1;
++                              else if (!strcasecmp(v->value, "hangup"))
++                                      confp->chan.pritransfer = 2;
++                              else
++                                      ast_log(LOG_WARNING, "'%s' is not a valid pri transfer value, should be 'no' , 'ect' or 'hangup' at line %d\n",
++                                              v->value, v->lineno);
+                       } else if (!strcasecmp(v->name, "priexclusive")) {
+                               confp->chan.priexclusive = ast_true(v->value);
+                       } else if (!strcasecmp(v->name, "internationalprefix")) {
+@@ -11071,6 +11816,10 @@ static int process_zap(struct zt_chan_co
+                               ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
+                       } else if (!strcasecmp(v->name, "unknownprefix")) {
+                               ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
++                      } else if (!strcasecmp(v->name, "nocid")) {
++                              ast_copy_string(confp->pri.nocid, v->value, sizeof(confp->pri.nocid));
++                      } else if (!strcasecmp(v->name, "withheldcid")) {
++                              ast_copy_string(confp->pri.withheldcid, v->value, sizeof(confp->pri.withheldcid));
+                       } else if (!strcasecmp(v->name, "resetinterval")) {
+                               if (!strcasecmp(v->value, "never"))
+                                       confp->pri.resetinterval = -1;
+@@ -11087,6 +11836,8 @@ static int process_zap(struct zt_chan_co
+                               ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
+                       } else if (!strcasecmp(v->name, "idledial")) {
+                               ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
++                      } else if (!strcasecmp(v->name, "pritrustusercid")) {
++                              confp->pri.usercid = ast_true(v->value);
+                       } else if (!strcasecmp(v->name, "overlapdial")) {
+                               confp->pri.overlapdial = ast_true(v->value);
+                       } else if (!strcasecmp(v->name, "pritimer")) {
+@@ -11389,6 +12140,7 @@ static int setup_zap(int reload)
+ #ifdef HAVE_PRI
+       if (!reload) {
+               for (x = 0; x < NUM_SPANS; x++) {
++                      pris[x].debugfd = -1;
+                       if (pris[x].pvts[0]) {
+                               if (start_pri(pris + x)) {
+                                       ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
+@@ -11436,7 +12188,10 @@ static int load_module(void)
+       ast_string_field_init(&inuse, 16);
+       ast_string_field_set(&inuse, name, "GR-303InUse");
+       ast_cli_register_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(struct ast_cli_entry));
++      ast_register_application(zapCD_app, app_zapCD, zapCD_synopsis, zapCD_tdesc);
++        ast_register_application(zapInband_app, app_zapInband, zapInband_synopsis, zapInband_tdesc);
+ #endif        
++      ast_register_application(zapEC_app, app_zapEC, zapEC_synopsis, zapEC_tdesc);
+       ast_cli_register_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
+       
+       memset(round_robin, 0, sizeof(round_robin));
+@@ -11470,6 +12225,7 @@ static int zt_sendtext(struct ast_channe
+       float scont = 0.0;
+       int index;
  
- /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
-@@ -237,10 +239,6 @@ AST_MUTEX_DEFINE_STATIC(iflock);
- static int ifcount = 0;
--#ifdef HAVE_PRI
--AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
--#endif
--
- /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
-    when it's doing something critical. */
- AST_MUTEX_DEFINE_STATIC(monlock);
-@@ -255,6 +253,7 @@ static enum ast_bridge_result zt_bridge(
- static int zt_sendtext(struct ast_channel *c, const char *text);
-+
- /*! \brief Avoid the silly zt_getevent which ignores a bunch of events */
- static inline int zt_get_event(int fd)
- {
-@@ -299,6 +298,27 @@ static int ringt_base = DEFAULT_RINGT;
- #define PRI_SPAN(p) (((p) >> 8) & 0xff)
- #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
-+struct zt_suspended_call {
-+      ast_mutex_t lock;               /* Mutex */
-+      char msn[AST_MAX_EXTENSION];    /* the MSN to which this parked call belongs */
-+      char callid[10];                        /* the callID provided by the user */
-+      int parked_at;                  /* extension in the call parking context */
-+      struct zt_suspended_call *next;
-+};
-+
-+struct zt_holded_call {
-+      ast_mutex_t lock;               /* Mutex */
-+      char msn[AST_MAX_EXTENSION];    /* the MSN to which this parked call belongs */
-+      char uniqueid[AST_MAX_EXTENSION];       /* unique id of the onhold channel */
-+      int tei;
-+      int cref;
-+      int alreadyhungup;
-+      struct ast_channel *channel;
-+      struct ast_channel *bridge;
-+      q931_call *call;        /* this also covers tei mumbojumbo */
-+      struct zt_holded_call *next;
-+};
 +
- struct zt_pri {
-       pthread_t master;                                               /*!< Thread of master */
-       ast_mutex_t lock;                                               /*!< Mutex */
-@@ -312,6 +332,8 @@ struct zt_pri {
-       int nsf;                                                        /*!< Network-Specific Facilities */
-       int dialplan;                                                   /*!< Dialing plan */
-       int localdialplan;                                              /*!< Local dialing plan */
-+      char nocid[AST_MAX_EXTENSION];                                  /*!< CallerID string to use if none provided */
-+      char withheldcid[AST_MAX_EXTENSION];                            /*!< CallerID string to use if CallerID is withheld */
-       char internationalprefix[10];                                   /*!< country access code ('00' for european dialplans) */
-       char nationalprefix[10];                                        /*!< area access code ('0' for european dialplans) */
-       char localprefix[20];                                           /*!< area access code + area code ('0'+area code for european dialplans) */
-@@ -323,6 +345,7 @@ struct zt_pri {
-       int prilogicalspan;                                             /*!< Logical span number within trunk group */
-       int numchans;                                                   /*!< Num of channels we represent */
-       int overlapdial;                                                /*!< In overlap dialing mode */
-+      int usercid;
-       int facilityenable;                                             /*!< Enable facility IEs */
-       struct pri *dchans[NUM_DCHANS];                                 /*!< Actual d-channels */
-       int dchanavail[NUM_DCHANS];                                     /*!< Whether each channel is available */
-@@ -338,6 +361,9 @@ struct zt_pri {
-       struct zt_pvt *pvts[MAX_CHANNELS];                              /*!< Member channel pvt structs */
-       struct zt_pvt *crvs;                                            /*!< Member CRV structs */
-       struct zt_pvt *crvend;                                          /*!< Pointer to end of CRV structs */
-+      struct zt_suspended_call *suspended_calls; /* Calls parked with SUSPEND messages */
-+      struct zt_holded_call *holded_calls; /* Calls on hold */
-+      int debugfd;
- };
+       index = zt_get_index(c, p, 0);
+       if (index < 0) {
+               ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
+--- a/configs/zapata.conf.sample
++++ b/configs/zapata.conf.sample
+@@ -123,9 +123,20 @@ switchtype=national
+ ; 
+ ; outofband:      Signal Busy/Congestion out of band with RELEASE/DISCONNECT
+ ; inband:         Signal Busy/Congestion using in-band tones
++; passthrough:          Listen to the telco
+ ;
+ ; priindication = outofband
+ ;
++; PRI/BRI transfers (HOLD -> SETUP -> ECT/Hangup)
++;
++; Configure how transfers are initiated. ECT should be preferred
++;
++; no:         no transfers allowed (results in hangup)
++; ect:        use ECT (facility)
++; hangup:     transfer on hangup (if your phones dont support ECT)
++;
++; pritransfer = ect
++;
+ ; If you need to override the existing channels selection routine and force all
+ ; PRI channels to be marked as exclusively selected, set this to yes.
+ ; priexclusive = yes
+Change the ABI of ast_channel_tech to add a new function, send_message that is
+to be used by channels wanting to send text messages with a destination number
+(mainly GSM).
+
+--- a/include/asterisk/channel.h
++++ b/include/asterisk/channel.h
+@@ -247,6 +247,11 @@ struct ast_channel_tech {
+       /*! \brief Display or transmit text */
+       int (* const send_text)(struct ast_channel *chan, const char *text);
  
++#if 0 /* we (Debian) disable that addition because of ABI breakage */
++      /*! \brief send a message */
++      int (* const send_message)(struct ast_channel *chan, const char *dest, const char *text, int ispdu);
++#endif
++
+       /*! \brief Display or send an image */
+       int (* const send_image)(struct ast_channel *chan, struct ast_frame *frame);
  
-@@ -455,6 +481,8 @@ static struct zt_pvt {
-       unsigned int echocanbridged:1;
-       unsigned int echocanon:1;
-       unsigned int faxhandled:1;                      /*!< Has a fax tone already been handled? */
-+                                                      /*!< KPJ: i will abuse this flag to implement a zapata option for dialing out
-+                                                          on a zap channel with EC to be off no matter what happens. */
-       unsigned int firstradio:1;
-       unsigned int hanguponpolarityswitch:1;
-       unsigned int hardwaredtmf:1;
-@@ -468,7 +496,8 @@ static struct zt_pvt {
-       unsigned int overlapdial:1;
-       unsigned int permcallwaiting:1;
-       unsigned int permhidecallerid:1;                /*!< Whether to hide our outgoing caller ID or not */
--      unsigned int priindication_oob:1;
-+      unsigned int priindication_oob:2;
-+      unsigned int pritransfer:2;
-       unsigned int priexclusive:1;
-       unsigned int pulse:1;
-       unsigned int pulsedial:1;                       /*!< whether a pulse dial phone is detected */
-@@ -505,6 +534,7 @@ static struct zt_pvt {
- #endif
-       char cid_num[AST_MAX_EXTENSION];
-       int cid_ton;                                    /*!< Type Of Number (TON) */
-+      int cid_pres;                                   /*!< Calling Presentation */
-       char cid_name[AST_MAX_EXTENSION];
-       char lastcid_num[AST_MAX_EXTENSION];
-       char lastcid_name[AST_MAX_EXTENSION];
-@@ -570,6 +600,8 @@ static struct zt_pvt {
-       struct zt_pvt *bearer;
-       struct zt_pvt *realcall;
-       q931_call *call;
-+      int tei;                                        /* channel in use by this tei */
-+      q931_call *holdedcall;
-       int prioffset;
-       int logicalspan;
- #endif        
-@@ -615,11 +647,14 @@ static struct zt_chan_conf zt_chan_conf_
-                       .minunused = 2,
-                       .idleext = "",
-                       .idledial = "",
-+                      .nocid = "No CID available",
-+                      .withheldcid = "CID withheld",
-                       .internationalprefix = "",
-                       .nationalprefix = "",
-                       .localprefix = "",
-                       .privateprefix = "",
-                       .unknownprefix = "",
-+                      .usercid = 0,
+@@ -689,6 +694,16 @@ struct ast_channel *ast_request_and_dial
  
-                       .resetinterval = 3600
-               },
-@@ -631,6 +666,8 @@ static struct zt_chan_conf zt_chan_conf_
-                       .mohinterpret = "default",
-                       .mohsuggest = "",
-                       .transfertobusy = 1,
-+                      .priindication_oob = 0,
-+                      .pritransfer = 0,
+ struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, const char *cidnum, const char *cidname, struct outgoing_helper *oh);
  
-                       .cid_signalling = CID_SIG_BELL,
-                       .cid_start = CID_START_RING,
-@@ -685,6 +722,8 @@ static int zt_indicate(struct ast_channe
- static int zt_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
- static int zt_setoption(struct ast_channel *chan, int option, void *data, int datalen);
- static int zt_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len); 
-+static void enable_dtmf_detect(struct zt_pvt *p);
-+static void disable_dtmf_detect(struct zt_pvt *p);
++/*! \brief "Requests" a channel for sending a message
++ * \param type type of channel to request
++ * \param data data to pass to the channel requester
++ * \param status status
++ * Request a channel of a given type, with data as optional information used
++ * by the low level module
++ * \return Returns 0 on success, -1 on failure.
++ */
++int ast_send_message(const char *type, void *data, char *to, char *from, char *message, int ispdu);
++
+ /*!\brief Register a channel technology (a new channel driver)
+  * Called by a channel module to register the kind of channels it supports.
+  * \param tech Structure defining channel technology or "type"
+@@ -910,6 +925,16 @@ int ast_set_write_format(struct ast_chan
+  */
+ int ast_sendtext(struct ast_channel *chan, const char *text);
  
- static const struct ast_channel_tech zap_tech = {
-       .type = "Zap",
-@@ -717,6 +756,13 @@ static const struct ast_channel_tech zap
- struct zt_pvt *round_robin[32];
++/*! \brief Sends message to a channel
++ * Write text to a display on a channel
++ * \param chan channel to act upon
++ * \param dest destination number/user
++ * \param text string of text to send on the channel
++ * \param ispdu message is in PDU format
++ * \return Returns 0 on success, -1 on failure
++ */
++int ast_sendmessage(struct ast_channel *chan, const char *dest, const char *text, int ispdu);
++
+ /*! \brief Receives a text character from a channel
+  * \param chan channel to act upon
+  * \param timeout timeout in milliseconds (0 for infinite wait)
+--- a/main/channel.c
++++ b/main/channel.c
+@@ -2472,6 +2472,21 @@ int ast_sendtext(struct ast_channel *cha
+       return res;
+ }
  
- #ifdef HAVE_PRI
-+struct app_tmp {
-+      char app[256];
-+      char data[256];
-+      struct ast_channel *chan;
-+      pthread_t t;
-+};
++int ast_sendmessage(struct ast_channel *chan, const char *dest, const char *text, int ispdu)
++{
++      int res = 0;
++      /* Stop if we're a zombie or need a soft hangup */
++      if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan))
++              return -1;
++      CHECK_BLOCKING(chan);
++#if 0 /* we (Debian) disable that addition because of ABI breakage */
++      if (chan->tech->send_message)
++              res = chan->tech->send_message(chan, dest, text, ispdu);
++#endif
++      ast_clear_flag(chan, AST_FLAG_BLOCKING);
++      return res;
++}
 +
- static inline int pri_grab(struct zt_pvt *pvt, struct zt_pri *pri)
- {
-       int res;
-@@ -1525,12 +1571,16 @@ static void zt_enable_ec(struct zt_pvt *
-       int res;
-       if (!p)
-               return;
-+      if (p->faxhandled)  {
-+              ast_log(LOG_DEBUG, "Not enabling echo cancellation on a fax/modem call\n");
-+              return;
-+      }
-       if (p->echocanon) {
-               ast_log(LOG_DEBUG, "Echo cancellation already on\n");
-               return;
-       }
-       if (p->digital) {
--              ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
-+              ast_log(LOG_DEBUG, "Echo cancellation does not make any sense on digital connections!\n");
-               return;
-       }
-       if (p->echocancel) {
-@@ -1557,7 +1607,7 @@ static void zt_train_ec(struct zt_pvt *p
+ int ast_senddigit_begin(struct ast_channel *chan, char digit)
  {
-       int x;
-       int res;
--      if (p && p->echocancel && p->echotraining) {
-+      if (p && p->echocancel && p->echotraining && (!p->digital) && (!p->faxhandled)) {
-               x = p->echotraining;
-               res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOTRAIN, &x);
-               if (res)
-@@ -1918,7 +1968,12 @@ static int zt_call(struct ast_channel *a
-               ast_log(LOG_WARNING, "Unable to flush input on channel %d\n", p->channel);
-       p->outgoing = 1;
+       /* Device does not support DTMF tones, lets fake
+@@ -4515,6 +4530,25 @@ void ast_channel_stop_silence_generator(
+ }
  
--      set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
-+      if (IS_DIGITAL(ast->transfercapability)) {
-+          set_actual_gain(p->subs[SUB_REAL].zfd, 0, 0, 0, p->law);
-+      } else {
-+          set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
++int ast_send_message(const char *type, void *data, char *to, char *from, char *message, int ispdu) {
++      struct ast_channel *chan = NULL;
++      int status;
++      int res = -1;
++
++      chan = ast_request(type, AST_FORMAT_SLINEAR, data, &status);
++      if (chan) {
++          if (from) {
++              ast_set_callerid(chan, from, from, from);
++          }
++          res = ast_sendmessage(chan, to, message, ispdu);
++          /* XXX what about message CDRs ??? XXX */
++          ast_hangup(chan);
++          return res;
 +      }
 +
-       mysig = p->sig;
-       if (p->outsigmod > -1)
-@@ -2149,6 +2204,7 @@ static int zt_call(struct ast_channel *a
-       case SIG_PRI:
-               /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
-               p->dialdest[0] = '\0';
-+              disable_dtmf_detect(p);
-               break;
-       default:
-               ast_log(LOG_DEBUG, "not yet implemented\n");
-@@ -2169,6 +2225,12 @@ static int zt_call(struct ast_channel *a
-               const char *rr_str;
-               int redirect_reason;
-+              if ((p->pri->nodetype == BRI_NETWORK_PTMP) || (p->pri->nodetype == BRI_NETWORK)) {
-+                  // pass NO audio when ringing an isdn phone
-+                  p->dialing = 1;
-+                  // maybe we could allow passing audio when calling a p2p PBX, but well... ;-)
-+              }
++      return res;
++}
 +
-               c = strchr(dest, '/');
-               if (c)
-                       c++;
-@@ -2191,6 +2253,7 @@ static int zt_call(struct ast_channel *a
-                       ast_mutex_unlock(&p->lock);
-                       return -1;
-               }
-+              strncpy(p->dnid, (c + p->stripmsd), sizeof(p->dnid)-1);
-               if (mysig != SIG_FXSKS) {
-                       p->dop.op = ZT_DIAL_OP_REPLACE;
-                       s = strchr(c + p->stripmsd, 'w');
-@@ -2214,6 +2277,8 @@ static int zt_call(struct ast_channel *a
-                       pri_rel(p->pri);
-                       ast_mutex_unlock(&p->lock);
-                       return -1;
-+              } else {
-+              //      ast_log(LOG_NOTICE, "call %d\n", p->call);
-               }
-               if (!(sr = pri_sr_new())) {
-                       ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
-@@ -2243,7 +2308,7 @@ static int zt_call(struct ast_channel *a
-               pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
-               pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 
-                                       (p->digital ? -1 : 
--                                              ((p->law == ZT_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
-+                                              ((p->law == ZT_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)), ast->lowlayercompat);
-               if (p->pri->facilityenable)
-                       pri_facility_enable(p->pri->pri);
-@@ -2507,8 +2572,10 @@ static int pri_find_dchan(struct zt_pri 
-       }
-       if (newslot < 0) {
-               newslot = 0;
--              ast_log(LOG_WARNING, "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
-+              if (pri->nodetype != BRI_CPE_PTMP) {
-+                  ast_log(LOG_WARNING, "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
-                       pri->dchannels[newslot]);
-+              }
-       }
-       if (old && (oldslot != newslot))
-               ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
-@@ -2518,6 +2585,16 @@ static int pri_find_dchan(struct zt_pri 
+ /*! \ brief Convert channel reloadreason (ENUM) to text string for manager event */
+ const char *channelreloadreason2txt(enum channelreloadreason reason)
+ {
+--- a/main/manager.c
++++ b/main/manager.c
+@@ -11,6 +11,9 @@
+  * the project provides a web site, mailing lists and IRC
+  * channels for your use.
+  *
++ * Copyright (C) 2003-2004, Junghanns.NET Gmbh
++ * Klaus-Peter Junghanns <kpj@junghanns.net>
++ *
+  * This program is free software, distributed under the terms of
+  * the GNU General Public License Version 2. See the LICENSE file
+  * at the top of the source tree.
+@@ -1427,6 +1430,49 @@ static int action_hangup(struct mansessi
+       return 0;
  }
- #endif
  
-+static int zt_setlaw(int zfd, int law)
++static char mandescr_message[] =
++"Description: Send a message\n"
++"Variables: \n"
++"     Channel: The destination channel(e.g. SIP/phone1)\n"
++"     From:    \n"
++"     Message: The message to send\n";
++
++static int action_message(struct mansession *s, const struct message *m)
 +{
++      const char *name = astman_get_header(m, "Channel");
++      const char *from = astman_get_header(m, "From");
++      const char *message = astman_get_header(m, "Message");
++      const char *pdu = astman_get_header(m, "PDU");
++      char tmp[256];
++      char *tech, *data;
 +      int res;
-+      res = ioctl(zfd, ZT_SETLAW, &law);
-+      if (res)
-+              return res;
++      if (ast_strlen_zero(name) || (ast_strlen_zero(message) && ast_strlen_zero(pdu))) {
++              astman_send_error(s, m, "No channel or message/PDU specified");
++              return 0;
++      }
++      ast_copy_string(tmp, name, sizeof(tmp));
++      tech = tmp;
++      data = strchr(tmp, '/');
++      if (!data) {
++              astman_send_error(s, m, "Invalid channel\n");
++              return 0;
++      }
++      *data = '\0';
++      data++;
++      if (ast_strlen_zero(pdu)) {
++          res = ast_send_message(tech, (char *)data, (char *)name, (char *)from, (char *)message, 0);
++      } else {
++          res = ast_send_message(tech, (char *)data, (char *)name, (char *)from, (char *)pdu, 1);
++      }
++
++      if (res) {
++              astman_send_error(s, m, "Error sending message");
++              return 0;
++      }
++      astman_send_ack(s, m, "Message sent");
 +      return 0;
 +}
 +
+ static char mandescr_setvar[] = 
+ "Description: Set a global or local channel variable.\n"
+ "Variables: (Names marked with * are required)\n"
+@@ -2853,6 +2899,7 @@ int init_manager(void)
+               ast_manager_register2("Events", 0, action_events, "Control Event Flow", mandescr_events);
+               ast_manager_register2("Logoff", 0, action_logoff, "Logoff Manager", mandescr_logoff);
+               ast_manager_register2("Hangup", EVENT_FLAG_CALL, action_hangup, "Hangup Channel", mandescr_hangup);
++              ast_manager_register2("Message", EVENT_FLAG_CALL, action_message, "Send Message", mandescr_message);
+               ast_manager_register("Status", EVENT_FLAG_CALL, action_status, "Lists channel status" );
+               ast_manager_register2("Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable", mandescr_setvar );
+               ast_manager_register2("Getvar", EVENT_FLAG_CALL, action_getvar, "Gets a Channel Variable", mandescr_getvar );
+--- a/pbx/pbx_spool.c
++++ b/pbx/pbx_spool.c
+@@ -87,6 +87,10 @@ struct outgoing {
+       char app[256];
+       char data[256];
++      /* If SMS */
++      char message[256];
++      char pdu[256];
 +
- static int zt_hangup(struct ast_channel *ast)
- {
-       int res;
-@@ -2565,8 +2642,7 @@ static int zt_hangup(struct ast_channel 
-       if (option_debug)
-               ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
-               p->channel, index, p->subs[SUB_REAL].zfd, p->subs[SUB_CALLWAIT].zfd, p->subs[SUB_THREEWAY].zfd);
--      p->ignoredtmf = 0;
--      
-+
-       if (index > -1) {
-               /* Real channel, do some fixup */
-               p->subs[index].owner = NULL;
-@@ -2668,6 +2744,7 @@ static int zt_hangup(struct ast_channel 
+       /* If extension/context/priority */
+       char exten[256];
+       char context[256];
+@@ -181,6 +185,10 @@ static int apply_outgoing(struct outgoin
+                                       ast_copy_string(o->app, c, sizeof(o->app));
+                               } else if (!strcasecmp(buf, "data")) {
+                                       ast_copy_string(o->data, c, sizeof(o->data));
++                              } else if (!strcasecmp(buf, "message")) {
++                                      strncpy(o->message, c, sizeof(o->message) - 1);
++                              } else if (!strcasecmp(buf, "pdu")) {
++                                      strncpy(o->pdu, c, sizeof(o->pdu) - 1);
+                               } else if (!strcasecmp(buf, "maxretries")) {
+                                       if (sscanf(c, "%d", &o->maxretries) != 1) {
+                                               ast_log(LOG_WARNING, "Invalid max retries at line %d of %s\n", lineno, fn);
+@@ -241,8 +249,8 @@ static int apply_outgoing(struct outgoin
+               }
+       }
+       ast_copy_string(o->fn, fn, sizeof(o->fn));
+-      if (ast_strlen_zero(o->tech) || ast_strlen_zero(o->dest) || (ast_strlen_zero(o->app) && ast_strlen_zero(o->exten))) {
+-              ast_log(LOG_WARNING, "At least one of app or extension must be specified, along with tech and dest in file %s\n", fn);
++      if (ast_strlen_zero(o->tech) || ast_strlen_zero(o->dest) || ((ast_strlen_zero(o->app) && ast_strlen_zero(o->exten) && ast_strlen_zero(o->message) && ast_strlen_zero(o->pdu)))) {
++              ast_log(LOG_WARNING, "At least one of app or extension (or keyword message/pdu)must be specified, along with tech and dest in file %s\n", fn);
+               return -1;
+       }
+       return 0;
+@@ -332,6 +340,14 @@ static void *attempt_thread(void *data)
+               if (option_verbose > 2)
+                       ast_verbose(VERBOSE_PREFIX_3 "Attempting call on %s/%s for application %s(%s) (Retry %d)\n", o->tech, o->dest, o->app, o->data, o->retries);
+               res = ast_pbx_outgoing_app(o->tech, AST_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->app, o->data, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL);
++      } else if (!ast_strlen_zero(o->message)) {
++              if (option_verbose > 2)
++                      ast_verbose(VERBOSE_PREFIX_3 "Attempting to send message on %s/%s (Retry %d)\n", o->tech, o->dest, o->retries);
++              res = ast_send_message(o->tech, o->dest, o->dest, (ast_strlen_zero(o->cid_name) ? o->cid_num : o->cid_name), o->message, 0);
++      } else if (!ast_strlen_zero(o->pdu)) {
++              if (option_verbose > 2)
++                      ast_verbose(VERBOSE_PREFIX_3 "Attempting to send message in PDU format on %s/%s (Retry %d)\n", o->tech, o->dest, o->retries);
++              res = ast_send_message(o->tech, o->dest, o->dest, (ast_strlen_zero(o->cid_name) ? o->cid_num : o->cid_name), o->pdu, 1);
+       } else {
+               if (option_verbose > 2)
+                       ast_verbose(VERBOSE_PREFIX_3 "Attempting call on %s/%s for %s@%s:%d (Retry %d)\n", o->tech, o->dest, o->exten, o->context,o->priority, o->retries);
+@@ -348,9 +364,14 @@ static void *attempt_thread(void *data)
+                       safe_append(o, time(NULL), "EndRetry");
+               }
+       } else {
++          if (!ast_strlen_zero(o->message)) {
++              if (option_verbose > 2)
++                  ast_verbose(VERBOSE_PREFIX_2 "Message sent to %s/%s\n", o->tech, o->dest);
++          } else {
+               ast_log(LOG_NOTICE, "Call completed to %s/%s\n", o->tech, o->dest);
+               ast_log(LOG_EVENT, "Queued call to %s/%s completed\n", o->tech, o->dest);
+-              remove_from_queue(o, "Completed");
++          }
++          remove_from_queue(o, "Completed");
        }
+       free_outgoing(o);
+       return NULL;
+--- a/include/asterisk/monitor.h
++++ b/include/asterisk/monitor.h
+@@ -38,6 +38,8 @@ struct ast_channel_monitor {
+       char write_filename[FILENAME_MAX];
+       char filename_base[FILENAME_MAX];
+       int filename_changed;
++      char target_url[FILENAME_MAX];
++      char target_script[FILENAME_MAX];
+       char *format;
+       int joinfiles;
+       enum AST_MONITORING_STATE state;
+@@ -46,7 +48,7 @@ struct ast_channel_monitor {
  
-       if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
-+              int outgoing = p->outgoing;
-               p->owner = NULL;
-               p->ringt = 0;
-               p->distinctivering = 0;
-@@ -2710,7 +2787,7 @@ static int zt_hangup(struct ast_channel 
-                                               pri_call_set_useruser(p->call, useruser);
- #endif
+ /* Start monitoring a channel */
+ int ast_monitor_start(struct ast_channel *chan, const char *format_spec,
+-                    const char *fname_base, int need_lock );
++                    const char *fname_base, const char *target_url, const char *target_script, int need_lock );
  
--                                              pri_hangup(p->pri->pri, p->call, -1);
-+                                              pri_hangup(p->pri->pri, p->call, -1, -1);
-                                               p->call = NULL;
-                                               if (p->bearer) 
-                                                       p->bearer->call = NULL;
-@@ -2730,7 +2807,28 @@ static int zt_hangup(struct ast_channel 
-                                                       if (atoi(cause))
-                                                               icause = atoi(cause);
-                                               }
--                                              pri_hangup(p->pri->pri, p->call, icause);
-+
-+                                              pri_hangup(p->pri->pri, p->call, icause, -1);
-+
-+                                              /* if we send a rel9999ease complete we wont ge no hangup event, so clear the call here */
-+                                              if (icause == 34 || icause == 44 || icause == 82 || icause == 1 || icause == 81 || icause == 17) {
-+                                                  if ((ast->_state == AST_STATE_RING) || (ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING) || (ast->_state == AST_STATE_RESERVED)) {
-+                                                      p->call = NULL;
-+                                                  } else {
-+                                                      ast_log(LOG_ERROR, "What is wrong with you? You cannot use cause %d number when in state %d!\n", icause, ast->_state);
-+                                                      icause = 16; /* Note, in pri_hangup() libpri will already override the cause */
-+                                                  }
-+                                              } 
-+                                              
-+                                              if (p->pri->nodetype == BRI_NETWORK_PTMP) {
-+                                                  if ((icause == 16 || icause == -1) && (ast->_state != AST_STATE_UP)) {
-+                                                      if (outgoing) {
-+                                                          p->call = NULL;
-+                                                      }
-+                                                  }
-+                                              }
-+                                              
-+                                              
-                                       }
-                                       if (res < 0) 
-                                               ast_log(LOG_WARNING, "pri_disconnect failed\n");
-@@ -2914,10 +3012,14 @@ static int zt_answer(struct ast_channel 
-                       p->proceeding = 1;
-                       res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
-                       pri_rel(p->pri);
-+                      /* stop ignoring inband dtmf */
-+                      enable_dtmf_detect(p);
-               } else {
-                       ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
-                       res = -1;
-               }
-+              /* the audio path is complete now, train the echo canceler */
-+              zt_train_ec(p);
-               break;
- #endif
-       case 0:
-@@ -3554,6 +3656,15 @@ static int zt_fixup(struct ast_channel *
+ /* Stop monitoring a channel */
+ int ast_monitor_stop(struct ast_channel *chan, int need_lock);
+--- a/res/res_monitor.c
++++ b/res/res_monitor.c
+@@ -130,7 +130,7 @@ static int ast_monitor_set_state(struct 
+ /* Start monitoring a channel */
+ int ast_monitor_start(        struct ast_channel *chan, const char *format_spec,
+-              const char *fname_base, int need_lock)
++              const char *fname_base, const char *target_url, const char *target_script, int need_lock)
  {
-       struct zt_pvt *p = newchan->tech_pvt;
-       int x;
-+      if (newchan && newchan->tech_pvt) {
-+          p = newchan->tech_pvt;
-+      }
-+      if (!p) {
-+          if (newchan) {
-+              ast_log(LOG_ERROR, "channel %s has no tech_pvt structure\n", newchan->name);
-+          }
-+          return 0;
-+      }
-       ast_mutex_lock(&p->lock);
-       ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
-       if (p->owner == oldchan) {
-@@ -3763,8 +3874,10 @@ static void zt_handle_dtmfup(struct ast_
-                                       pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
-                                       if (ast_async_goto(ast, target_context, "fax", 1))
-                                               ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
--                              } else
-+                              } else {
-+                                  if (option_verbose > 2)
-                                       ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
-+                              }
-                       } else if (option_debug)
-                               ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
-               } else if (option_debug)
-@@ -3923,7 +4036,7 @@ static struct ast_frame *zt_handle_event
-                               if (p->call) {
-                                       if (p->pri && p->pri->pri) {
-                                               if (!pri_grab(p, p->pri)) {
--                                                      pri_hangup(p->pri->pri, p->call, -1);
-+                                                      pri_hangup(p->pri->pri, p->call, -1, -1);
-                                                       pri_destroycall(p->pri->pri, p->call);
-                                                       p->call = NULL;
-                                                       pri_rel(p->pri);
-@@ -4974,7 +5087,7 @@ static struct ast_frame  *zt_read(struct
-               p->subs[index].f.data = NULL;
-               p->subs[index].f.datalen= 0;
-       }
--      if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect  || p->callprogress) && !index) {
-+      if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
-               /* Perform busy detection. etc on the zap line */
-               f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
-               if (f) {
-@@ -4986,8 +5099,9 @@ static struct ast_frame  *zt_read(struct
-                               }
-                       } else if (f->frametype == AST_FRAME_DTMF) {
- #ifdef HAVE_PRI
--                              if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
--                                      /* Don't accept in-band DTMF when in overlap dial mode */
-+                              if (p->sig==SIG_PRI && p->pri && p->pri->overlapdial && p->ignoredtmf) {
-+                                      /* Don't accept in-band DTMF when in overlap dial mode 
-+                                         or when in non-overlap overlapdialing mode ... */
-                                       f->frametype = AST_FRAME_NULL;
-                                       f->subclass = 0;
-                               }
-@@ -5062,7 +5176,9 @@ static int zt_write(struct ast_channel *
- #endif
-       /* Write a frame of (presumably voice) data */
-       if (frame->frametype != AST_FRAME_VOICE) {
--              if (frame->frametype != AST_FRAME_IMAGE)
-+              if (frame->frametype == AST_FRAME_TEXT) {
-+                      ast_log(LOG_NOTICE, "text\n");
-+              } else if (frame->frametype != AST_FRAME_IMAGE)
-                       ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
+       int res = 0;
+       char tmp[256];
+@@ -154,6 +154,11 @@ int ast_monitor_start(    struct ast_channe
+                       return -1;
+               }
++              if (target_url)
++                  ast_copy_string(monitor->target_url, target_url, sizeof(monitor->target_url));
++              if (target_script)
++                  ast_copy_string(monitor->target_script, target_script, sizeof(monitor->target_script));
++
+               /* Determine file names */
+               if (!ast_strlen_zero(fname_base)) {
+                       int directory = strchr(fname_base, '/') ? 1 : 0;
+@@ -297,6 +302,8 @@ int ast_monitor_stop(struct ast_channel 
+               if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) {
+                       char tmp[1024];
+                       char tmp2[1024];
++                      char tmp3[1024];
++                      int result;
+                       const char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format;
+                       char *name = chan->monitor->filename_base;
+                       int directory = strchr(name, '/') ? 1 : 0;
+@@ -325,8 +332,13 @@ int ast_monitor_stop(struct ast_channel 
+                               snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s%s%s-\"* ) &",tmp, dir, absolute, name); /* remove legs when done mixing */
+                               ast_copy_string(tmp, tmp2, sizeof(tmp));
+                       }
+-                      ast_log(LOG_DEBUG,"monitor executing %s\n",tmp);
+-                      if (ast_safe_system(tmp) == -1)
++                      if (!ast_strlen_zero(chan->monitor->target_script) && !ast_strlen_zero(chan->monitor->target_url)) {
++                              snprintf(tmp3,sizeof(tmp3), "( %s& nice -19 %s \"%s/%s.%s\" \"%s\" ) &",tmp, chan->monitor->target_script , dir, name, format, chan->monitor->target_url); 
++                              ast_copy_string(tmp, tmp3, sizeof(tmp));
++                      }
++                      ast_log(LOG_NOTICE,"monitor executing %s\n",tmp);
++                      result = ast_safe_system(tmp);
++                      if (result == -1)
+                               ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
+               }
+               
+@@ -467,7 +479,7 @@ static int start_monitor_exec(struct ast
                return 0;
        }
-@@ -5130,7 +5246,7 @@ static int zt_indicate(struct ast_channe
-               switch (condition) {
-               case AST_CONTROL_BUSY:
- #ifdef HAVE_PRI
--                      if (p->priindication_oob && p->sig == SIG_PRI) {
-+                      if ((p->priindication_oob == 1) && p->sig == SIG_PRI) {
-                               chan->hangupcause = AST_CAUSE_USER_BUSY;
-                               chan->_softhangup |= AST_SOFTHANGUP_DEV;
-                               res = 0;
-@@ -5212,7 +5328,7 @@ static int zt_indicate(struct ast_channe
-               case AST_CONTROL_CONGESTION:
-                       chan->hangupcause = AST_CAUSE_CONGESTION;
- #ifdef HAVE_PRI
--                      if (p->priindication_oob && p->sig == SIG_PRI) {
-+                      if ((p->priindication_oob == 1) && p->sig == SIG_PRI) {
-                               chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
-                               chan->_softhangup |= AST_SOFTHANGUP_DEV;
-                               res = 0;
-@@ -5406,8 +5522,12 @@ static struct ast_channel *zt_new(struct
-       if (state == AST_STATE_RING)
-               tmp->rings = 1;
-       tmp->tech_pvt = i;
-+#ifdef HAVE_PRI
-+      if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS) || (i->sig == SIG_PRI)) {
-+#else
-       if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
--              /* Only FXO signalled stuff can be picked up */
-+#endif
-+              /* Only FXO signalled stuff can be picked up */ /* i dont think so, mr. ulaw! we alaws like to pick up BRIs/PRIs */
-               tmp->callgroup = i->callgroup;
-               tmp->pickupgroup = i->pickupgroup;
-       }
-@@ -5537,6 +5657,7 @@ static void *ss_thread(void *data)
-       int len = 0;
-       int res;
-       int index;
-+      int network;
  
-       /* in the bizarre case where the channel has become a zombie before we
-          even get started here, abort safely
-@@ -5565,10 +5686,17 @@ static void *ss_thread(void *data)
-               len = strlen(exten);
-               res = 0;
-               while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
--                      if (len && !ast_ignore_pattern(chan->context, exten))
-+                      if (len && !ast_ignore_pattern(chan->context, exten)) {
-                               tone_zone_play_tone(p->subs[index].zfd, -1);
--                      else
--                              tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
-+                      } else {
-+                              network = p->pri->nodetype == PRI_NETWORK || p->pri->nodetype == BRI_NETWORK || p->pri->nodetype == BRI_NETWORK_PTMP;
-+                              if (network) {
-+                                  tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
-+                              } else {
-+                                  /* cpe be quiet */
-+                                  tone_zone_play_tone(p->subs[index].zfd, -1);
-+                              }
-+                      }
-                       if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
-                               timeout = matchdigittimeout;
-                       else
-@@ -6784,18 +6912,44 @@ static int handle_init_event(struct zt_p
-               break;
-       case ZT_EVENT_NOALARM:
-               i->inalarm = 0;
-+#ifdef HAVE_PRI
-+              if (i->pri) {
-+                  if ((i->pri->nodetype == BRI_CPE_PTMP) || (i->pri->nodetype == BRI_CPE)) {
-+                      /* dont annoy BRI TE mode users with layer2layer alarms */
-+                  } else {
-+                      ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
-+                      manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
-+                            "Channel: %d\r\n", i->channel);
-+                  }
-+              }
-+#else
-               ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
-               manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
-                       "Channel: %d\r\n", i->channel);
-+#endif
-               break;
-       case ZT_EVENT_ALARM:
-               i->inalarm = 1;
-               res = get_alarms(i);
-+#ifdef HAVE_PRI
-+              if (i->pri) {
-+                  if ((i->pri->nodetype == BRI_CPE_PTMP) || (i->pri->nodetype == BRI_CPE)) {
-+                      /* dont annoy BRI TE mode users with layer2layer alarms */
-+                  } else {
-+                      ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", i->channel, alarm2str(res));
-+                      manager_event(EVENT_FLAG_SYSTEM, "Alarm",
-+                            "Alarm: %s\r\n"
-+                            "Channel: %d\r\n",
-+                            alarm2str(res), i->channel);
-+                  }
-+              }
-+#else
-               ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", i->channel, alarm2str(res));
-               manager_event(EVENT_FLAG_SYSTEM, "Alarm",
-                       "Alarm: %s\r\n"
-                       "Channel: %d\r\n",
-                       alarm2str(res), i->channel);
-+#endif
-               /* fall thru intentionally */
-       case ZT_EVENT_ONHOOK:
-               if (i->radio)
-@@ -6839,8 +6993,10 @@ static int handle_init_event(struct zt_p
-                       zt_set_hook(i->subs[SUB_REAL].zfd, ZT_ONHOOK);
-                       break;
-               case SIG_PRI:
--                      zt_disable_ec(i);
--                      res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
-+                      if (event != ZT_EVENT_ALARM) {
-+                          zt_disable_ec(i);
-+                          res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
-+                      }
-                       break;
-               default:
-                       ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
-@@ -7139,6 +7295,8 @@ static int pri_resolve_span(int *span, i
-               } else {
-                       if (si->totalchans == 31) { /* if it's an E1 */
-                               pris[*span].dchannels[0] = 16 + offset;
-+                      } else if (si->totalchans == 3) { /* if it's an S0 ZAPBRI */
-+                              pris[*span].dchannels[0] = 3 + offset;
-                       } else {
-                               pris[*span].dchannels[0] = 24 + offset;
-                       }
-@@ -7391,6 +7549,11 @@ static struct zt_pvt *mkintf(int channel
-                                                       destroy_zt_pvt(&tmp);
-                                                       return NULL;
-                                               }
-+                                              if ((pris[span].localdialplan) && (pris[span].localdialplan != conf.pri.localdialplan)) {
-+                                                      ast_log(LOG_ERROR, "Span %d is already a %s local dialing plan\n", span + 1, dialplan2str(pris[span].localdialplan));
-+                                                      destroy_zt_pvt(&tmp);
-+                                                      return NULL;
-+                                              }
-                                               if (pris[span].minunused && (pris[span].minunused != conf.pri.minunused)) {
-                                                       ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf.pri.minunused);
-                                                       destroy_zt_pvt(&tmp);
-@@ -7408,6 +7571,11 @@ static struct zt_pvt *mkintf(int channel
-                                                       return NULL;
-                                               }
-                                               pris[span].nodetype = conf.pri.nodetype;
-+
-+                                              if (conf.pri.nodetype == BRI_NETWORK_PTMP) {
-+                                                  pris[span].dchanavail[0] =  DCHAN_AVAILABLE;
-+                                                  pri_find_dchan(&pris[span]);
-+                                              }
-                                               pris[span].switchtype = myswitchtype;
-                                               pris[span].nsf = conf.pri.nsf;
-                                               pris[span].dialplan = conf.pri.dialplan;
-@@ -7416,9 +7584,14 @@ static struct zt_pvt *mkintf(int channel
-                                               pris[span].minunused = conf.pri.minunused;
-                                               pris[span].minidle = conf.pri.minidle;
-                                               pris[span].overlapdial = conf.pri.overlapdial;
-+                                              pris[span].usercid = conf.pri.usercid;
-+                                              pris[span].suspended_calls = NULL;
-+                                              pris[span].holded_calls = NULL;
-                                               pris[span].facilityenable = conf.pri.facilityenable;
-                                               ast_copy_string(pris[span].idledial, conf.pri.idledial, sizeof(pris[span].idledial));
-                                               ast_copy_string(pris[span].idleext, conf.pri.idleext, sizeof(pris[span].idleext));
-+                                              ast_copy_string(pris[span].nocid, conf.pri.nocid, sizeof(pris[span].nocid));
-+                                              ast_copy_string(pris[span].withheldcid, conf.pri.withheldcid, sizeof(pris[span].withheldcid));
-                                               ast_copy_string(pris[span].internationalprefix, conf.pri.internationalprefix, sizeof(pris[span].internationalprefix));
-                                               ast_copy_string(pris[span].nationalprefix, conf.pri.nationalprefix, sizeof(pris[span].nationalprefix));
-                                               ast_copy_string(pris[span].localprefix, conf.pri.localprefix, sizeof(pris[span].localprefix));
-@@ -7554,6 +7727,7 @@ static struct zt_pvt *mkintf(int channel
-               tmp->restrictcid = conf.chan.restrictcid;
-               tmp->use_callingpres = conf.chan.use_callingpres;
-               tmp->priindication_oob = conf.chan.priindication_oob;
-+              tmp->pritransfer = conf.chan.pritransfer;
-               tmp->priexclusive = conf.chan.priexclusive;
-               if (tmp->usedistinctiveringdetection) {
-                       if (!tmp->use_callerid) {
-@@ -7833,7 +8007,7 @@ static int pri_find_empty_chan(struct zt
-                       break;
-               if (!backwards && (x >= pri->numchans))
-                       break;
--              if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
-+              if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner && !pri->pvts[x]->call) {
-                       ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n", 
-                               pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
-                       return x;
-@@ -8029,6 +8203,11 @@ static struct ast_channel *zt_request(co
-                                       p->digital = 1;
-                                       if (tmp)
-                                               tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
-+                              } else if (opt == 'm') {
-+                                      /* If this is a modem/fax call, pretend to have the fax handled and dont do EC */
-+                                      p->faxhandled = 1;
-+                                      if (tmp)
-+                                          tmp->transfercapability = AST_TRANS_CAP_3_1K_AUDIO;
-                               } else {
-                                       ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
+-      res = ast_monitor_start(chan, format, fname_base, 1);
++      res = ast_monitor_start(chan, format, fname_base, NULL, NULL, 1);
+       if (res < 0)
+               res = ast_monitor_change_fname(chan, fname_base, 1);
+       ast_monitor_setjoinfiles(chan, joinfiles);
+@@ -506,6 +518,8 @@ static int start_monitor_action(struct m
+       const char *fname = astman_get_header(m, "File");
+       const char *format = astman_get_header(m, "Format");
+       const char *mix = astman_get_header(m, "Mix");
++      const char *target_url = astman_get_header(m, "TargetURL");
++      const char *target_script = astman_get_header(m, "TargetScript");
+       char *d;
+       
+       if (ast_strlen_zero(name)) {
+@@ -530,7 +544,7 @@ static int start_monitor_action(struct m
+                       *d = '-';
+       }
+       
+-      if (ast_monitor_start(c, format, fname, 1)) {
++      if (ast_monitor_start(c, format, fname, target_url, target_script, 1)) {
+               if (ast_monitor_change_fname(c, fname, 1)) {
+                       astman_send_error(s, m, "Could not start monitoring channel");
+                       ast_channel_unlock(c);
+--- a/apps/app_queue.c
++++ b/apps/app_queue.c
+@@ -2891,13 +2891,13 @@ static int try_calling(struct queue_ent 
+                               else
+                                       which = peer;
+                               if (monitorfilename)
+-                                      ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1 );
++                                      ast_monitor_start(which, qe->parent->monfmt, monitorfilename, NULL, NULL, 1 );
+                               else if (qe->chan->cdr)
+-                                      ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, 1 );
++                                      ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, NULL, NULL, 1 );
+                               else {
+                                       /* Last ditch effort -- no CDR, make up something */
+                                       snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random());
+-                                      ast_monitor_start(which, qe->parent->monfmt, tmpid, 1 );
++                                      ast_monitor_start(which, qe->parent->monfmt, tmpid, NULL, NULL, 1 );
                                }
-@@ -8062,13 +8241,14 @@ next:
-                               *cause = AST_CAUSE_BUSY;
-               } else if (groupmatched) {
-                       *cause = AST_CAUSE_CONGESTION;
-+              } else {
-+                      *cause = AST_CAUSE_CONGESTION;
-               }
+                               if (qe->parent->monjoin)
+                                       ast_monitor_setjoinfiles(which, 1);
+--- a/channels/chan_agent.c
++++ b/channels/chan_agent.c
+@@ -419,7 +419,7 @@ static int __agent_start_monitoring(stru
+               if ((pointer = strchr(filename, '.')))
+                       *pointer = '-';
+               snprintf(tmp, sizeof(tmp), "%s%s", savecallsin, filename);
+-              ast_monitor_start(ast, recordformat, tmp, needlock);
++              ast_monitor_start(ast, recordformat, tmp, NULL, NULL, needlock);
+               ast_monitor_setjoinfiles(ast, 1);
+               snprintf(tmp2, sizeof(tmp2), "%s%s.%s", urlprefix, filename, recordformatext);
+ #if 0
+--- a/include/asterisk/devicestate.h
++++ b/include/asterisk/devicestate.h
+@@ -47,7 +47,7 @@ extern "C" {
+ #define AST_DEVICE_ONHOLD     8
+ /*! \brief Devicestate watcher call back */
+-typedef int (*ast_devstate_cb_type)(const char *dev, int state, void *data);
++typedef int (*ast_devstate_cb_type)(const char *dev, int state, void *data, char *cid_num, char *cid_name);
+ /*!  \brief Devicestate provider call back */
+ typedef int (*ast_devstate_prov_cb_type)(const char *data);
+@@ -92,7 +92,7 @@ int ast_device_state_changed(const char 
+  * callbacks for the changed extensions
+  * Returns 0 on success, -1 on failure
+  */
+-int ast_device_state_changed_literal(const char *device);
++int ast_device_state_changed_literal(const char *device, const char *cid_num, const char *cid_name);
+ /*! \brief Registers a device state change callback 
+  * \param callback Callback
+--- a/main/devicestate.c
++++ b/main/devicestate.c
+@@ -78,6 +78,8 @@ static AST_LIST_HEAD_STATIC(devstate_cbs
+ struct state_change {
+       AST_LIST_ENTRY(state_change) list;
++      char cid_num[AST_MAX_EXTENSION];
++      char cid_name[AST_MAX_EXTENSION];
+       char device[1];
+ };
+@@ -277,7 +279,7 @@ void ast_devstate_del(ast_devstate_cb_ty
+ /*! \brief Notify callback watchers of change, and notify PBX core for hint updates
+       Normally executed within a separate thread
+ */
+-static void do_state_change(const char *device)
++static void do_state_change(const char *device, char *cid_num, char *cid_name)
+ {
+       int state;
+       struct devstate_cb *devcb;
+@@ -288,13 +290,13 @@ static void do_state_change(const char *
+       AST_LIST_LOCK(&devstate_cbs);
+       AST_LIST_TRAVERSE(&devstate_cbs, devcb, list)
+-              devcb->callback(device, state, devcb->data);
++              devcb->callback(device, state, devcb->data, cid_num, cid_name);
+       AST_LIST_UNLOCK(&devstate_cbs);
+-      ast_hint_state_changed(device);
++      ast_hint_state_changed(device, cid_num, cid_name);
+ }
+-static int __ast_device_state_changed_literal(char *buf, int norecurse)
++static int __ast_device_state_changed_literal(char *buf, int norecurse, char *cid_num, char *cid_name)
+ {
+       char *device;
+       struct state_change *change;
+@@ -308,10 +310,16 @@ static int __ast_device_state_changed_li
+       if (change_thread == AST_PTHREADT_NULL || !(change = ast_calloc(1, sizeof(*change) + strlen(device)))) {
+               /* we could not allocate a change struct, or */
+               /* there is no background thread, so process the change now */
+-              do_state_change(device);
++              do_state_change(device, cid_num, cid_name);
+       } else {
+               /* queue the change */
+               strcpy(change->device, device);
++              if (cid_num && (!ast_strlen_zero(cid_num))) {
++                  strncpy(change->cid_num, cid_num, sizeof(change->cid_num) - 1);
++              }
++              if (cid_name && (!ast_strlen_zero(cid_name))) {
++                  strncpy(change->cid_name, cid_name, sizeof(change->cid_name) - 1);
++              }
+               AST_LIST_LOCK(&state_changes);
+               AST_LIST_INSERT_TAIL(&state_changes, change, list);
+               if (AST_LIST_FIRST(&state_changes) == change)
+@@ -329,17 +337,23 @@ static int __ast_device_state_changed_li
+        */
+       if (!norecurse && (tmp = strrchr(device, '-'))) {
+               *tmp = '\0';
+-              __ast_device_state_changed_literal(device, 1);
++              __ast_device_state_changed_literal(device, 1, cid_num, cid_name);
        }
-               
-       return tmp;
+       
+       return 1;
  }
  
--
- #ifdef HAVE_PRI
- static struct zt_pvt *pri_find_crv(struct zt_pri *pri, int crv)
+-int ast_device_state_changed_literal(const char *dev)
++int ast_device_state_changed_literal(const char *dev, const char *cid_num, const char *cid_name)
  {
-@@ -8082,6 +8262,58 @@ static struct zt_pvt *pri_find_crv(struc
-       return NULL;
+       char *buf;
++      char *buf2 = NULL;
++      char *buf3 = NULL;
+       buf = ast_strdupa(dev);
+-      return __ast_device_state_changed_literal(buf, 0);
++      if (cid_num)
++          buf2 = ast_strdupa(cid_num);
++      if (cid_name)
++          buf3 = ast_strdupa(cid_name);
++      return __ast_device_state_changed_literal(buf, 0, buf2, buf3);
  }
  
-+static int pri_find_tei(struct zt_pri *pri, q931_call *c, int tei)
-+{
-+      int x=0;
-+      for (x=0;x<pri->numchans;x++) {
-+              if (!pri->pvts[x]) continue;
-+              if ((pri->pvts[x]->tei == tei) && (pri->pvts[x]-> call != c)) {
-+                  return x;
-+              }
-+      }
-+      return -1;
-+}
-+
-+static struct zt_holded_call *pri_get_callonhold(struct zt_pri *pri, int cref, int tei) {
-+      struct zt_holded_call *zhc = pri->holded_calls;
-+      struct zt_holded_call *zhctemp = NULL;
-+
-+      while (zhc) {
-+          if ((zhc->tei == tei) && ((zhc->cref == cref) || (cref == -1))) {
-+              return zhc;
-+          }                   
-+          zhctemp = zhc;
-+          if (zhc) zhc = zhc->next;
-+      }
-+      return NULL;    
-+}
-+
-+static int pri_destroy_callonhold(struct zt_pri *pri, struct zt_holded_call *onhold) {
-+      struct zt_holded_call *zhc = pri->holded_calls;
-+      struct zt_holded_call *zhctemp = NULL;
+ /*! \brief Accept change notification, add it to change queue */
+@@ -351,7 +365,7 @@ int ast_device_state_changed(const char 
+       va_start(ap, fmt);
+       vsnprintf(buf, sizeof(buf), fmt, ap);
+       va_end(ap);
+-      return __ast_device_state_changed_literal(buf, 0);
++      return __ast_device_state_changed_literal(buf, 0, NULL, NULL);
+ }
+ /*! \brief Go through the dev state change queue and update changes in the dev state thread */
+@@ -366,7 +380,7 @@ static void *do_devstate_changes(void *d
+               if (cur) {
+                       /* we got an entry, so unlock the list while we process it */
+                       AST_LIST_UNLOCK(&state_changes);
+-                      do_state_change(cur->device);
++                      do_state_change(cur->device, cur->cid_num, cur->cid_name);
+                       free(cur);
+                       AST_LIST_LOCK(&state_changes);
+               } else {
+--- a/include/asterisk/channel.h
++++ b/include/asterisk/channel.h
+@@ -613,8 +613,13 @@ int ast_channel_datastore_remove(struct 
+ /*! \brief Find a datastore on a channel */
+ struct ast_datastore *ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, char *uid);
++extern ast_mutex_t uniquelock;
 +
-+      while (zhc) {
-+          if (zhc == onhold) {
-+              if (zhctemp) {
-+                  zhctemp->next = zhc->next;
-+                  zhc = zhctemp;
-+              } else {
-+                  pri->holded_calls = zhc->next;
-+                  zhc = pri->holded_calls;
-+                  zhctemp = NULL;
-+              }
-+          }                   
-+          zhctemp = zhc;
-+          if (zhc) zhc = zhc->next;
-+      }
-+      if (onhold) {
-+          free(onhold);
-+          onhold = NULL;
-+          return 1;   
-+      }
-+      return 0;       
-+}
++/*! \brief Change the state of a channel and the callerid of the calling channel*/
++int ast_setstate_and_callerid(struct ast_channel *chan, enum ast_channel_state state, char *cid_num, char *cid_name);
 +
+ /*! \brief Change the state of a channel */
+-int ast_setstate(struct ast_channel *chan, enum ast_channel_state);
++int ast_setstate(struct ast_channel *chan, enum ast_channel_state state);
  
- static int pri_find_principle(struct zt_pri *pri, int channel)
- {
-@@ -8113,7 +8345,9 @@ static int pri_find_principle(struct zt_
- static int pri_fixup_principle(struct zt_pri *pri, int principle, q931_call *c)
- {
-       int x;
-+      int res = 0;
-       struct zt_pvt *crv;
-+      char tmpname[256];
-       if (!c) {
-               if (principle < 0)
-                       return -1;
-@@ -8141,6 +8375,7 @@ static int pri_fixup_principle(struct zt
-                               }
-                               /* Fix it all up now */
-                               pri->pvts[principle]->owner = pri->pvts[x]->owner;
-+                              pri->pvts[principle]->outgoing = pri->pvts[x]->outgoing;
-                               if (pri->pvts[principle]->owner) {
-                                       ast_string_field_build(pri->pvts[principle]->owner, name, 
-                                                              "Zap/%d:%d-%d", pri->trunkgroup,
-@@ -8148,13 +8383,48 @@ static int pri_fixup_principle(struct zt
-                                       pri->pvts[principle]->owner->tech_pvt = pri->pvts[principle];
-                                       pri->pvts[principle]->owner->fds[0] = pri->pvts[principle]->subs[SUB_REAL].zfd;
-                                       pri->pvts[principle]->subs[SUB_REAL].owner = pri->pvts[x]->subs[SUB_REAL].owner;
--                              } else
-+                              } else {
-                                       ast_log(LOG_WARNING, "Whoa, there's no  owner, and we're having to fix up channel %d to channel %d\n", pri->pvts[x]->channel, pri->pvts[principle]->channel);
-+                              }
-                               pri->pvts[principle]->call = pri->pvts[x]->call;
-+                              pri->pvts[principle]->dsp = pri->pvts[x]->dsp;
-+                              pri->pvts[principle]->alreadyhungup = pri->pvts[x]->alreadyhungup;
-+                              pri->pvts[principle]->digital = pri->pvts[x]->digital;
-+                              pri->pvts[principle]->faxhandled = pri->pvts[x]->faxhandled;
-+  
-+                              if ((pri->nodetype == BRI_CPE_PTMP) || (pri->nodetype == BRI_CPE)) { 
-+                                  /* this might also apply for other pri types! */
-+                                  pri->pvts[principle]->law = pri->pvts[x]->law;
-+                                  if (ioctl(pri->pvts[principle]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &pri->pvts[principle]->law) == -1)
-+                                      ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", pri->pvts[principle]->channel, pri->pvts[principle]->law);
-+                                  res = zt_setlaw(pri->pvts[principle]->subs[SUB_REAL].zfd, pri->pvts[principle]->law);
-+                                  if (res < 0) 
-+                                      ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[principle]->channel);
-+                                  if (!pri->pvts[principle]->digital) {
-+                                      res = set_actual_gain(pri->pvts[principle]->subs[SUB_REAL].zfd, 0, pri->pvts[principle]->rxgain, pri->pvts[principle]->txgain, pri->pvts[principle]->law);
-+                                  } else {
-+                                      res = set_actual_gain(pri->pvts[principle]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[principle]->law);
-+                                  }
-+                                  if (res < 0) 
-+                                      ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[principle]->channel);
-+                                  zt_confmute(pri->pvts[x], 0);
-+                                  update_conf(pri->pvts[x]);
-+                                  reset_conf(pri->pvts[x]);
-+                                  restore_gains(pri->pvts[x]);
-+                                  zt_disable_ec(pri->pvts[x]);
-+                                  zt_setlinear(pri->pvts[x]->subs[SUB_REAL].zfd, 0);
-+                              }
-+  
-+                              if (pri->pvts[principle]->owner) {
-+                                  snprintf(tmpname, sizeof(tmpname), "Zap/%d-1", pri->pvts[principle]->channel);
-+                                  ast_change_name(pri->pvts[principle]->owner, tmpname);
-+                              }
-+
-                               /* Free up the old channel, now not in use */
-                               pri->pvts[x]->subs[SUB_REAL].owner = NULL;
-                               pri->pvts[x]->owner = NULL;
-                               pri->pvts[x]->call = NULL;
-+                              pri->pvts[x]->dsp = NULL;
-                       }
-                       return principle;
-               }
-@@ -8183,7 +8453,9 @@ static int pri_fixup_principle(struct zt
-               }
-               crv = crv->next;
-       }
--      ast_log(LOG_WARNING, "Call specified, but not found?\n");
-+      if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
-+          ast_log(LOG_WARNING, "Call specified, but not found?\n");
-+      }
-       return -1;
- }
+ /*! \brief Create a channel structure 
+     \return Returns NULL on failure to allocate.
+--- a/main/channel.c
++++ b/main/channel.c
+@@ -1261,7 +1261,7 @@ void ast_channel_free(struct ast_channel
+       free(chan);
+       AST_LIST_UNLOCK(&channels);
  
-@@ -8242,86 +8514,21 @@ static void *do_idle_thread(void *vchan)
- #ifndef PRI_RESTART
- #error "Upgrade your libpri"
- #endif
--static void zt_pri_message(struct pri *pri, char *s)
-+static void zt_pri_message(char *s, int span)
- {
--      int x, y;
--      int dchan = -1, span = -1;
--      int dchancount = 0;
--
--      if (pri) {
--              for (x = 0; x < NUM_SPANS; x++) {
--                      for (y = 0; y < NUM_DCHANS; y++) {
--                              if (pris[x].dchans[y])
--                                      dchancount++;
--
--                              if (pris[x].dchans[y] == pri)
--                                      dchan = y;
--                      }
--                      if (dchan >= 0) {
--                              span = x;
--                              break;
--                      }
--                      dchancount = 0;
--              }
--              if ((dchan >= 0) && (span >= 0)) {
--                      if (dchancount > 1)
--                              ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
--                      else
--                              ast_verbose("%s", s);
--              } else
--                      ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
--      } else
--              ast_verbose("%s", s);
--
--      ast_mutex_lock(&pridebugfdlock);
--
--      if (pridebugfd >= 0)
--              write(pridebugfd, s, strlen(s));
--
--      ast_mutex_unlock(&pridebugfdlock);
-+      ast_verbose("%d %s", span, s);
+-      ast_device_state_changed_literal(name);
++      ast_device_state_changed_literal(name, NULL, NULL);
  }
  
--static void zt_pri_error(struct pri *pri, char *s)
-+static void zt_pri_error(char *s, int span)
- {
--      int x, y;
--      int dchan = -1, span = -1;
--      int dchancount = 0;
--
--      if (pri) {
--              for (x = 0; x < NUM_SPANS; x++) {
--                      for (y = 0; y < NUM_DCHANS; y++) {
--                              if (pris[x].dchans[y])
--                                      dchancount++;
--
--                              if (pris[x].dchans[y] == pri)
--                                      dchan = y;
--                      }
--                      if (dchan >= 0) {
--                              span = x;
--                              break;
--                      }
--                      dchancount = 0;
--              }
--              if ((dchan >= 0) && (span >= 0)) {
--                      if (dchancount > 1)
--                              ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
--                      else
--                              ast_log(LOG_ERROR, "%s", s);
--              } else
--                      ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
--      } else
--              ast_log(LOG_ERROR, "%s", s);
--
--      ast_mutex_lock(&pridebugfdlock);
--
--      if (pridebugfd >= 0)
--              write(pridebugfd, s, strlen(s));
--
--      ast_mutex_unlock(&pridebugfdlock);
-+      ast_log(LOG_WARNING, "%d %s", span, s);
+ struct ast_datastore *ast_channel_datastore_alloc(const struct ast_datastore_info *info, char *uid)
+@@ -3673,7 +3673,7 @@ void ast_set_callerid(struct ast_channel
+       ast_channel_unlock(chan);
  }
  
- static int pri_check_restart(struct zt_pri *pri)
+-int ast_setstate(struct ast_channel *chan, enum ast_channel_state state)
++int ast_setstate_and_callerid(struct ast_channel *chan, enum ast_channel_state state, char *cid_num, char *cid_name)
  {
-+      if ((pri->nodetype != PRI_NETWORK) && (pri->nodetype != PRI_CPE)) {
-+          return 0;
-+      }
-       do {
-               pri->resetpos++;
-       } while ((pri->resetpos < pri->numchans) &&
-@@ -8405,13 +8612,30 @@ static void apply_plan_to_number(char *b
-       }
+       int oldstate = chan->_state;
+@@ -3681,7 +3681,7 @@ int ast_setstate(struct ast_channel *cha
+               return 0;
+       chan->_state = state;
+-      ast_device_state_changed_literal(chan->name);
++      ast_device_state_changed_literal(chan->name, cid_num, cid_name);
+       /* setstate used to conditionally report Newchannel; this is no more */
+       manager_event(EVENT_FLAG_CALL,
+                     "Newstate",
+@@ -3698,6 +3698,11 @@ int ast_setstate(struct ast_channel *cha
+       return 0;
  }
  
--static int zt_setlaw(int zfd, int law)
--{
--      int res;
--      res = ioctl(zfd, ZT_SETLAW, &law);
--      if (res)
--              return res;
--      return 0;
-+static void pri_make_callerid(struct zt_pri *pri, char *callerid, int callerid_len, char *callingnum, int callingnum_len, int callingplan, int callingpres, int stripmsd) {
-+    if (callingnum && (callingnum_len > stripmsd)) {
-+      callingnum += stripmsd;
-+    }
-+    switch (callingplan) {
-+      case PRI_INTERNATIONAL_ISDN:
-+          snprintf(callerid, callerid_len, "%s%s", pri->internationalprefix, callingnum);
-+          break;
-+      case PRI_NATIONAL_ISDN:
-+          snprintf(callerid, callerid_len, "%s%s", pri->nationalprefix, callingnum);
-+          break;
-+      case PRI_LOCAL_ISDN:
-+          snprintf(callerid, callerid_len, "%s%s", pri->localprefix, callingnum);
-+          break;
-+      case PRI_PRIVATE:
-+          snprintf(callerid, callerid_len, "%s%s", pri->privateprefix, callingnum);
-+          break;
-+      case PRI_UNKNOWN:
-+          snprintf(callerid, callerid_len, "%s%s", pri->unknownprefix, callingnum);
-+          break;
-+      default:
-+          snprintf(callerid, callerid_len, "%s", callingnum);
-+          break;
-+    }
++int ast_setstate(struct ast_channel *chan, enum ast_channel_state state)
++{
++    return ast_setstate_and_callerid(chan, state, NULL, NULL);
++}
++
+ /*! \brief Find bridged channel */
+ struct ast_channel *ast_bridged_channel(struct ast_channel *chan)
+ {
+--- a/include/asterisk/pbx.h
++++ b/include/asterisk/pbx.h
+@@ -63,7 +63,7 @@ struct ast_ignorepat;
+ struct ast_sw;
+ /*! \brief Typedef for devicestate and hint callbacks */
+-typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data);
++typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data, char *cid_num, char *cid_name);
+ /*! \brief Data structure associated with a custom dialplan function */
+ struct ast_custom_function {
+@@ -875,7 +875,7 @@ int ast_func_read(struct ast_channel *ch
+  */
+ int ast_func_write(struct ast_channel *chan, char *function, const char *value);
+-void ast_hint_state_changed(const char *device);
++void ast_hint_state_changed(const char *device, char *cid_num, char *cid_name);
+ #if defined(__cplusplus) || defined(c_plusplus)
+ }
+--- a/main/pbx.c
++++ b/main/pbx.c
+@@ -2022,7 +2022,7 @@ int ast_extension_state(struct ast_chann
+       return ast_extension_state2(e);                 /* Check all devices in the hint */
  }
  
- static void *pri_dchannel(void *vpri)
-@@ -8591,15 +8815,44 @@ static void *pri_dchannel(void *vpri)
-                                       /* Check for an event */
-                                       x = 0;
-                                       res = ioctl(pri->fds[which], ZT_GETEVENT, &x);
--                                      if (x) 
-+                                      if ((pri->nodetype != BRI_CPE) && (pri->nodetype != BRI_CPE_PTMP)) {
-+                                          /* dont annoy BRI TE mode users with layer2layer alarms */
-+                                          if (x)
-                                               ast_log(LOG_NOTICE, "PRI got event: %s (%d) on %s D-channel of span %d\n", event2str(x), x, pri_order(which), pri->span);
-+                                      }
-                                       /* Keep track of alarm state */ 
-                                       if (x == ZT_EVENT_ALARM) {
-                                               pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
-                                               pri_find_dchan(pri);
-+                                              if ((pri->nodetype == BRI_CPE) || (pri->nodetype == BRI_CPE_PTMP)) {
-+                                                  if (pri->pri) {
-+                                                      for (i=0; i<pri->numchans; i++) {
-+                                                          struct zt_pvt *p = pri->pvts[i];
-+                                                          if (p) {
-+                                                              if (p->call) {
-+                                                                  if (p->pri && p->pri->pri) {
-+                                                                      pri_destroycall(p->pri->pri, p->call);
-+                                                                      p->call = NULL;
-+                                                                      p->tei = -1;
-+                                                                  } else
-+                                                                      ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
-+                                                              }
-+                                                              if (p->owner)
-+                                                                  p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+                                                              p->inalarm = 1;
-+                                                          }
-+                                                      }
-+                                                      pri_shutdown(pri->pri);
-+                                                  }
-+                                              }
-                                       } else if (x == ZT_EVENT_NOALARM) {
--                                              pri->dchanavail[which] |= DCHAN_NOTINALARM;
--                                              pri_restart(pri->dchans[which]);
-+                                              if ((pri->nodetype == BRI_CPE) || (pri->nodetype == BRI_CPE_PTMP)) {
-+                                                  pri->dchanavail[which] |= DCHAN_NOTINALARM;
-+                                              //    pri->dchanavail[which] |= DCHAN_UP;
-+                                              } else {
-+                                                  pri->dchanavail[which] |= DCHAN_NOTINALARM;
-+                                                  pri_restart(pri->dchans[which]);
-+                                              }
-                                       }
-                               
-                                       if (option_debug)
-@@ -8611,8 +8864,7 @@ static void *pri_dchannel(void *vpri)
-                                       break;
-                       }
-               } else if (errno != EINTR)
--                      ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
--
-+                      ast_log(LOG_WARNING, "pri_event returned error %d (%s) on span %d\n", errno, strerror(errno), pri->span);
-               if (e) {
-                       if (pri->debug)
-                               pri_dump_event(pri->dchans[which], e);
-@@ -8625,32 +8877,86 @@ static void *pri_dchannel(void *vpri)
+-void ast_hint_state_changed(const char *device)
++void ast_hint_state_changed(const char *device, char *cid_num, char *cid_name)
+ {
+       struct ast_hint *hint;
  
-                       switch (e->e) {
-                       case PRI_EVENT_DCHAN_UP:
--                              if (option_verbose > 1) 
--                                      ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
--                              pri->dchanavail[which] |= DCHAN_UP;
--                              if (!pri->pri) pri_find_dchan(pri);
-+                              if (pri->nodetype == BRI_NETWORK_PTMP) {
-+                                  if (option_verbose > 3) 
-+                                      ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up for TEI %d\n", pri_order(which), pri->span, e->gen.tei);
-+                                  pri->dchanavail[which] |= DCHAN_UP;
-+                                  if (!pri->pri) pri_find_dchan(pri);
-+  
-+                                  /* Note presense of D-channel */
-+                                  time(&pri->lastreset);
-+  
-+                                  pri->resetting = 0;
-+                                  /* Take the channels from inalarm condition */
-+                                  for (i=0; i<pri->numchans; i++)
-+                                      if (pri->pvts[i]) {
-+                                              pri->pvts[i]->inalarm = 0;
-+                                      }
-+                              } else {
-+                                  if (pri->nodetype == BRI_CPE_PTMP) {
-+                                      if (option_verbose > 3) 
-+                                          ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
-+                                  } else {
-+                                      if (option_verbose > 1) 
-+                                          ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
-+                                  }
-+                                  pri->dchanavail[which] |= DCHAN_UP;
-+                                  if (!pri->pri) pri_find_dchan(pri);
--                              /* Note presense of D-channel */
--                              time(&pri->lastreset);
-+                                  /* Note presense of D-channel */
-+                                  time(&pri->lastreset);
--                              /* Restart in 5 seconds */
--                              if (pri->resetinterval > -1) {
-+                                  /* Restart in 5 seconds */
-+                                  if (pri->resetinterval > -1) {
-                                       pri->lastreset -= pri->resetinterval;
-                                       pri->lastreset += 5;
--                              }
--                              pri->resetting = 0;
--                              /* Take the channels from inalarm condition */
--                              for (i = 0; i < pri->numchans; i++)
-+                                  }
-+                                  pri->resetting = 0;
-+                                  /* Take the channels from inalarm condition */
-+                                  for (i = 0; i < pri->numchans; i++)
-                                       if (pri->pvts[i]) {
-                                               pri->pvts[i]->inalarm = 0;
-                                       }
-+                              }
-                               break;
-                       case PRI_EVENT_DCHAN_DOWN:
--                              if (option_verbose > 1) 
--                                      ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
--                              pri->dchanavail[which] &= ~DCHAN_UP;
--                              pri_find_dchan(pri);
--                              if (!pri_is_up(pri)) {
-+                              if (pri->nodetype == BRI_NETWORK_PTMP) {
-+                                  if (option_verbose > 3) 
-+                                      ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down for TEI %d\n", pri_order(which), pri->span, e->gen.tei);
-+                                  // PTMP BRIs have N dchans, handled by libpri
-+                                  if (e->gen.tei == 0) break;
-+                                  /* Hangup active channels */
-+                                  for (i=0; i<pri->numchans; i++) {
-+                                      struct zt_pvt *p = pri->pvts[i];
-+                                      if (p) {
-+                      //              ast_log(LOG_NOTICE, "chan %d tei %d\n",i,p->tei);
-+                                          if (p->tei == e->gen.tei) {
-+                                              if (p->call) {
-+                                                      if (p->pri && p->pri->pri) {
-+                                                              pri_hangup(p->pri->pri, p->call, -1, -1);
-+                                                              pri_destroycall(p->pri->pri, p->call);
-+                                                              p->call = NULL;
-+                                                      } else
-+                                                              ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
-+                                              }
-+                                              if (p->owner)
-+                                                  p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+                                              p->inalarm = 1;
-+                                              p->tei = -1;
-+                                          }
-+                                      }
-+                                  } 
-+                              } else {
-+                                  if (pri->nodetype == BRI_CPE_PTMP) {
-+                                      if (option_verbose > 3) 
-+                                          ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
-+                                  } else {
-+                                      if (option_verbose > 1) 
-+                                          ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
-+                                  }
-+                                  pri->dchanavail[which] &= ~DCHAN_UP;
-+                                  pri_find_dchan(pri);
-+                                  if (!pri_is_up(pri)) {
-                                       pri->resetting = 0;
-                                       /* Hangup active channels and put them in alarm mode */
-                                       for (i = 0; i < pri->numchans; i++) {
-@@ -8660,12 +8966,13 @@ static void *pri_dchannel(void *vpri)
-                                                               /* T309 is not enabled : hangup calls when alarm occurs */
-                                                               if (p->call) {
-                                                                       if (p->pri && p->pri->pri) {
--                                                                              pri_hangup(p->pri->pri, p->call, -1);
-+                                                                              pri_hangup(p->pri->pri, p->call, -1, -1);
-                                                                               pri_destroycall(p->pri->pri, p->call);
-                                                                               p->call = NULL;
-                                                                       } else
-                                                                               ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
-                                                               }
-+                                                              p->tei = -1;
-                                                               if (p->realcall) {
-                                                                       pri_hangup_all(p->realcall, pri);
-                                                               } else if (p->owner)
-@@ -8674,6 +8981,7 @@ static void *pri_dchannel(void *vpri)
-                                                       p->inalarm = 1;
-                                               }
-                                       }
-+                                  }
-                               }
-                               break;
-                       case PRI_EVENT_RESTART:
-@@ -8708,8 +9016,8 @@ static void *pri_dchannel(void *vpri)
-                                                               pri_destroycall(pri->pri, pri->pvts[x]->call);
-                                                               pri->pvts[x]->call = NULL;
-                                                       }
--                                                      if (pri->pvts[chanpos]->realcall) 
--                                                              pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
-+                                                      if (pri->pvts[x]->realcall) 
-+                                                              pri_hangup_all(pri->pvts[x]->realcall, pri);
-                                                       else if (pri->pvts[x]->owner)
-                                                               pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-                                                       ast_mutex_unlock(&pri->pvts[x]->lock);
-@@ -8743,7 +9051,6 @@ static void *pri_dchannel(void *vpri)
-                                       }
-                               }
-                               break;
--                              
-                       case PRI_EVENT_INFO_RECEIVED:
-                               chanpos = pri_find_principle(pri, e->ring.channel);
-                               if (chanpos < 0) {
-@@ -8752,9 +9059,11 @@ static void *pri_dchannel(void *vpri)
-                               } else {
-                                       chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
-                                       if (chanpos > -1) {
-+//                                    ast_log(LOG_NOTICE, "INFO received on  channel %d/%d span %d\n", 
-+//                                            PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
-                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                               /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
--                                              if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
-+                                              if (pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
-                                                       /* how to do that */
-                                                       int digitlen = strlen(e->ring.callednum);
-                                                       char digit;
-@@ -8766,6 +9075,14 @@ static void *pri_dchannel(void *vpri)
-                                                                       zap_queue_frame(pri->pvts[chanpos], &f, pri);
-                                                               }
-                                                       }
-+                                                      if (!pri->overlapdial) {
-+                                                          strncat(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
-+                                                          if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten + 1)) {
-+                                                              tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
-+                                                          } else {
-+                                                              tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
-+                                                          }
-+                                                      } 
-                                               }
-                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                       }
-@@ -8773,36 +9090,59 @@ static void *pri_dchannel(void *vpri)
-                               break;
-                       case PRI_EVENT_RING:
-                               crv = NULL;
--                              if (e->ring.channel == -1)
-+                              if (e->ring.channel == -1) {
-+                                      /* if no channel specified find one empty */
-                                       chanpos = pri_find_empty_chan(pri, 1);
--                              else
-+                              } else {
-                                       chanpos = pri_find_principle(pri, e->ring.channel);
-+                              }
-                               /* if no channel specified find one empty */
-                               if (chanpos < 0) {
--                                      ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 
--                                              PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
-+                                      /* no channel specified and no free channel. this is a callwating SETUP */
-+                                      if (e->ring.channel <= 0) {
-+                                          if (option_verbose > 2)
-+                                              ast_verbose(VERBOSE_PREFIX_3 "Ignoring callwaiting SETUP on channel %d/%d span %d %d\n", PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span, e->ring.channel);
-+                                          pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_USER_BUSY, -1);
-+                                          break;
-+                                      }
-                               } else {
-+                                      /* ok, we got a b channel for this call, lock it */
-                                       ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                       if (pri->pvts[chanpos]->owner) {
--                                              if (pri->pvts[chanpos]->call == e->ring.call) {
--                                                      ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 
-+                                          /* safety check, for messed up retransmissions? */
-+                                          if (pri->pvts[chanpos]->call == e->ring.call) {
-+                                              ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 
-                                                               PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
--                                                      break;
-+                                              ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+                                              chanpos = -1;
-+                                              break;
-+                                          } else {
-+                                              ast_log(LOG_WARNING, "Ring requested on channel %d/%d already in use on span %d. Hanging up owner.\n", 
-+                                              PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
-+                                              if (pri->pvts[chanpos]->realcall) {
-+                                                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
-                                               } else {
--                                                      /* This is where we handle initial glare */
--                                                      ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d.  Attempting to renegotiating channel.\n", 
--                                                      PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
--                                                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
--                                                      chanpos = -1;
-+                                                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+                                                      /* XXX destroy the call here, so we can accept the retransmission as a new call */
-+                                                      pri_destroycall(pri->pri, e->ring.call);
-                                               }
--                                      }
--                                      if (chanpos > -1)
-                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+                                              chanpos = -1;
-+                                              break;
-+                                          }
-+                                      }
-+                                      if (chanpos > -1) {
-+                                              /* everything is ok with the b channel */
-+                                          ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+                                      }
-                               }
--                              if ((chanpos < 0) && (e->ring.flexible))
--                                      chanpos = pri_find_empty_chan(pri, 1);
-+                              /* actually, we already got a valid channel by now */
-                               if (chanpos > -1) {
-                                       ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+                                      /* dont detect dtmfs before the signalling is done */
-+                                      disable_dtmf_detect(pri->pvts[chanpos]);
-+                                      /* this channel is owned by this TEI */
-+                                      pri->pvts[chanpos]->tei = e->ring.tei;
-                                       if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
-                                               /* Should be safe to lock CRV AFAIK while bearer is still locked */
-                                               crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
-@@ -8816,13 +9156,14 @@ static void *pri_dchannel(void *vpri)
-                                                               ast_log(LOG_WARNING, "Call received for busy CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
-                                                       } else
-                                                               ast_log(LOG_NOTICE, "Call received for unconfigured CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
--                                                      pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
-+                                                      pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE, -1);
-                                                       if (crv)
-                                                               ast_mutex_unlock(&crv->lock);
-                                                       ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                                       break;
-                                               }
+@@ -2053,11 +2053,11 @@ void ast_hint_state_changed(const char *
+               /* For general callbacks */
+               for (cblist = statecbs; cblist; cblist = cblist->next)
+-                      cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
++                      cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data, cid_num, cid_name);
+               /* For extension callbacks */
+               for (cblist = hint->callbacks; cblist; cblist = cblist->next)
+-                      cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
++                      cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data, cid_num, cid_name);
+               hint->laststate = state;        /* record we saw the change */
+       }
+@@ -2252,7 +2252,7 @@ static int ast_remove_hint(struct ast_ex
+                               /* Notify with -1 and remove all callbacks */
+                               cbprev = cblist;
+                               cblist = cblist->next;
+-                              cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data);
++                              cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data, NULL, NULL);
+                               free(cbprev);
+                       }
+                       hint->callbacks = NULL;
+@@ -4021,7 +4021,7 @@ void ast_merge_contexts_and_delete(struc
+                       while (thiscb) {
+                               prevcb = thiscb;
+                               thiscb = thiscb->next;
+-                              prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data);
++                              prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data, NULL, NULL);
+                               free(prevcb);
+                       }
+               } else {
+--- a/channels/chan_sip.c
++++ b/channels/chan_sip.c
+@@ -1342,7 +1342,7 @@ static void ast_quiet_chan(struct ast_ch
+ static int attempt_transfer(struct sip_dual *transferer, struct sip_dual *target);
+ /*--- Device monitoring and Device/extension state handling */
+-static int cb_extensionstate(char *context, char* exten, int state, void *data);
++static int cb_extensionstate(char *context, char* exten, int state, void *data, char *cid_num, char *cid_name);
+ static int sip_devicestate(void *data);
+ static int sip_poke_noanswer(const void *data);
+ static int sip_poke_peer(struct sip_peer *peer);
+@@ -8593,7 +8593,7 @@ static void sip_peer_hold(struct sip_pvt
+ /*! \brief Callback for the devicestate notification (SUBSCRIBE) support subsystem
+ \note If you add an "hint" priority to the extension in the dial plan,
+       you will get notifications on device state changes */
+-static int cb_extensionstate(char *context, char* exten, int state, void *data)
++static int cb_extensionstate(char *context, char* exten, int state, void *data, char *cid_num, char *cid_name)
+ {
+       struct sip_pvt *p = data;
+@@ -12783,7 +12783,7 @@ static void handle_response(struct sip_p
+                                       if (ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE)) {
+                                               /* Ready to send the next state we have on queue */
+                                               ast_clear_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE);
+-                                              cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p);
++                                              cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p, NULL, NULL);
                                        }
-+                                      /* assign call to b channel */
-                                       pri->pvts[chanpos]->call = e->ring.call;
-                                       apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
-                                       if (pri->pvts[chanpos]->use_callerid) {
-@@ -8847,34 +9188,82 @@ static void *pri_dchannel(void *vpri)
+                               }
+                       } else if (sipmethod == SIP_REGISTER) 
+@@ -13036,7 +13036,7 @@ static void handle_response(struct sip_p
+                                       if (ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE)) {
+                                               /* Ready to send the next state we have on queue */
+                                               ast_clear_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE);
+-                                              cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p);
++                                              cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p, NULL, NULL);
                                        }
-                                       apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
-                                                            e->ring.redirectingnum, e->ring.callingplanrdnis);
-+                                      /* get callingpres */
-+                                      pri->pvts[chanpos]->cid_pres = e->ring.callingpres;
-+                                      switch (e->ring.callingpres) {
-+                                          case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
-+                                          case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
-+                                          case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
-+                                          case PRES_PROHIB_NETWORK_NUMBER:
-+                                              ast_copy_string(pri->pvts[chanpos]->cid_name, pri->withheldcid, sizeof(pri->pvts[chanpos]->cid_name));
-+                                              break;
-+                                          case PRES_NUMBER_NOT_AVAILABLE:
-+                                              ast_copy_string(pri->pvts[chanpos]->cid_name, pri->nocid, sizeof(pri->pvts[chanpos]->cid_name));
-+                                              break;
-+                                      }
-                                       /* If immediate=yes go to s|1 */
-                                       if (pri->pvts[chanpos]->immediate) {
-                                               if (option_verbose > 2)
-                                                       ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
-                                               pri->pvts[chanpos]->exten[0] = 's';
-                                               pri->pvts[chanpos]->exten[1] = '\0';
--                                      }
--                                      /* Get called number */
--                                      else if (!ast_strlen_zero(e->ring.callednum)) {
--                                              ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
--                                              ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
--                                      } else if (pri->overlapdial)
--                                              pri->pvts[chanpos]->exten[0] = '\0';
--                                      else {
--                                              /* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
--                                              pri->pvts[chanpos]->exten[0] = 's';
--                                              pri->pvts[chanpos]->exten[1] = '\0';
--                                      }
--                                      /* Set DNID on all incoming calls -- even immediate */
--                                      if (!ast_strlen_zero(e->ring.callednum))
--                                              ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
--                                      /* No number yet, but received "sending complete"? */
--                                      if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
-+                                      } else if (ast_strlen_zero(e->ring.callednum)) {
-+                                          /* called party number is empty */
-+                                          if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
-+                                              if (!pri->overlapdial) {
-+                                                  // be able to set digittimeout for BRI phones
-+                                                  pri->pvts[chanpos]->exten[0] = 's';
-+                                                  pri->pvts[chanpos]->exten[1] = '\0';
-+                                                  tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
-+                                              } else {
-+                                                  pri->pvts[chanpos]->exten[0] = '\0';
-+                                              }
-+                                          } else {
-+                                              if (pri->nodetype == BRI_CPE) { 
-+                                                  /* fix for .at p2p bri lines */
-+                                                  pri->pvts[chanpos]->exten[0] = 's';
-+                                                  pri->pvts[chanpos]->exten[1] = '\0';
-+                                              } else if (pri->overlapdial) {
-+                                                  pri->pvts[chanpos]->exten[0] = '\0';
-+                                              } else {
-+                                                  /* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
-+                                                  pri->pvts[chanpos]->exten[0] = 's';
-+                                                  pri->pvts[chanpos]->exten[1] = '\0';
-+                                              }
-+                                          }
-+                                          /* No number yet, but received "sending complete"? */
-+                                          if (e->ring.complete) {
-                                               if (option_verbose > 2)
-                                                       ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
-                                               pri->pvts[chanpos]->exten[0] = 's';
-                                               pri->pvts[chanpos]->exten[1] = '\0';
--                                      }
-+                                          }
-+                                      } else {
-+                                              /* Get called number */
-+                                              pri_make_callerid(pri, pri->pvts[chanpos]->dnid, sizeof(pri->pvts[chanpos]->dnid), e->ring.callednum, sizeof(e->ring.callednum),  e->ring.calledplan, 0, pri->pvts[chanpos]->stripmsd);
-+                                              pri_make_callerid(pri, pri->pvts[chanpos]->exten, sizeof(pri->pvts[chanpos]->exten), e->ring.callednum, sizeof(e->ring.callednum), e->ring.calledplan, 0, pri->pvts[chanpos]->stripmsd);
-+                                              if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
-+                                                  /* if we get the next digit we should stop the dialtone */
-+                                                  if (!pri->overlapdial) {
-+                                                      // with overlapdial=no the exten is always prefixed by "s"
-+                                                      if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten + 1)) {
-+                                                          tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
-+                                                      } else {
-+                                                          tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
-+                                                      }
-+                                                  } else {
-+                                                      if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten)) {
-+                                                          tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
-+                                                      } else {
-+                                                          tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
-+                                                      }
-+                                                  }
-+                                              }
-+                                      }
-+                                      /* Part 3: create channel, setup audio... */
-+                                      /* Set DNID on all incoming calls -- even immediate */
-+                                      if (!ast_strlen_zero(e->ring.callednum))
-+                                              strncpy(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid) - 1);
-                                       /* Make sure extension exists (or in overlap dial mode, can exist) */
-                                       if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
-                                               ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
-@@ -8893,19 +9282,36 @@ static void *pri_dchannel(void *vpri)
-                                               res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
-                                               if (res < 0) 
-                                                       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
--                                              res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
-+                                              if (IS_DIGITAL(e->ring.ctype)) {
-+                                                  res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[chanpos]->law);
-+                                              } else {
-+                                                  res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
-+                                              }
-                                               if (res < 0)
-                                                       ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
--                                              if (e->ring.complete || !pri->overlapdial) {
-+                                              if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
-+                                                  if (e->ring.complete || !pri->overlapdial) {
-                                                       /* Just announce proceeding */
-                                                       pri->pvts[chanpos]->proceeding = 1;
-                                                       pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
--                                              } else {
-+                                                  } else {
-                                                       if (pri->switchtype != PRI_SWITCH_GR303_TMC) 
-                                                               pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
-                                                       else
-                                                               pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
-+                                                  }
-+                                              } else {
-+                                                      /* BRI_NETWORK | BRI_NETWORK_PTMP */
-+                                                      if (pri->overlapdial || (!strcasecmp(pri->pvts[chanpos]->exten, "s"))) {
-+                                                          /* send a SETUP_ACKNOWLEDGE */
-+                                                          pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
-+                                                      } else {
-+                                                          /* send an ALERTING ??? wtf */
-+                                                      //    pri_acknowledge(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
-+                                                          pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
-+                                                      }
-                                               }
-+                                              /* overlapdial = yes  and the extension can be valid */
-                                               /* Get the use_callingpres state */
-                                               pri->pvts[chanpos]->callingpres = e->ring.callingpres;
-                                       
-@@ -8917,10 +9323,17 @@ static void *pri_dchannel(void *vpri)
-                                                               /* Set bearer and such */
-                                                               pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
-                                                               c = zt_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
-+                                                              if (c && (e->ring.lowlayercompat[0] > 0)) {
-+                                                                  memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
-+                                                              }
-                                                               pri->pvts[chanpos]->owner = &inuse;
-                                                               ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
-                                                       } else {
-                                                               c = zt_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
-+                                                              if (c && (e->ring.lowlayercompat[0] > 0)) {
-+                                                                  memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
-+                                                              }
-+                                                              zt_enable_ec(pri->pvts[chanpos]);  /* XXX rethink */
-                                                       }
+                               }
+                       } else if (sipmethod == SIP_BYE)
+--- a/apps/app_queue.c
++++ b/apps/app_queue.c
+@@ -721,7 +721,7 @@ static void *device_state_thread(void *d
+       return NULL;
+ }
+ /*! \brief Producer of the statechange queue */
+-static int statechange_queue(const char *dev, int state, void *ign)
++static int statechange_queue(const char *dev, int state, void *ign, char *cid_num, char *cid_name)
+ {
+       struct statechange *sc;
+--- a/include/asterisk/manager.h
++++ b/include/asterisk/manager.h
+@@ -55,6 +55,7 @@
+ #define EVENT_FLAG_AGENT              (1 << 5) /* Ability to read/set agent info */
+ #define EVENT_FLAG_USER                 (1 << 6) /* Ability to read/set user info */
+ #define EVENT_FLAG_CONFIG             (1 << 7) /* Ability to modify configurations */
++#define EVENT_FLAG_EXTENSIONSTATUS    (1 << 8) /* ExtensionStatus events */
+ /* Export manager structures */
+ #define AST_MAX_MANHEADERS 128
+--- a/main/manager.c
++++ b/main/manager.c
+@@ -129,6 +129,7 @@ static struct permalias {
+       { EVENT_FLAG_AGENT, "agent" },
+       { EVENT_FLAG_USER, "user" },
+       { EVENT_FLAG_CONFIG, "config" },
++      { EVENT_FLAG_EXTENSIONSTATUS, "extensionstatus" },
+       { -1, "all" },
+       { 0, "none" },
+ };
+@@ -2551,10 +2552,12 @@ int ast_manager_unregister(char *action)
+       return 0;
+ }
+-static int manager_state_cb(char *context, char *exten, int state, void *data)
++static int manager_state_cb(char *context, char *exten, int state, void *data, char *cid_num, char *cid_name)
+ {
++      char hint[256] = "";
++      ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten);
+       /* Notify managers of change */
+-      manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nStatus: %d\r\n", exten, context, state);
++      manager_event(EVENT_FLAG_EXTENSIONSTATUS, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nStatus: %d\r\nCallerID: \"%s\" <%s>\r\nHint: %s\r\n", exten, context, state, cid_num, cid_name, hint);
+       return 0;
+ }
+--- a/apps/app_devstate.c
++++ b/apps/app_devstate.c
+@@ -50,7 +50,7 @@ static struct ast_cli_entry  cli_dev_sta
+ static int devstate_cli(int fd, int argc, char *argv[])
+ {
+     char devName[128];
+-    if (argc != 3)
++    if ((argc != 3) && (argc != 4) && (argc != 5))
+         return RESULT_SHOWUSAGE;
+     if (ast_db_put("DEVSTATES", argv[1], argv[2]))
+@@ -58,7 +58,15 @@ static int devstate_cli(int fd, int argc
+         ast_log(LOG_DEBUG, "ast_db_put failed\n");
+     }
+     snprintf(devName, sizeof(devName), "DS/%s", argv[1]);
+-    ast_device_state_changed_literal(devName);
++    if (argc == 4) {
++        ast_log(LOG_NOTICE, "devname %s cid %s\n", devName, argv[3]);
++      ast_device_state_changed_literal(devName, argv[3], NULL);
++    } else if (argc == 5) {
++        ast_log(LOG_NOTICE, "devname %s cid %s cidname %s\n", devName, argv[3], argv[4]);
++      ast_device_state_changed_literal(devName, argv[3], argv[4]);
++    } else {
++      ast_device_state_changed_literal(devName, NULL, NULL);
++    }
+     return RESULT_SUCCESS;
+ }
+@@ -93,7 +101,7 @@ static int devstate_exec(struct ast_chan
+     }
+     snprintf(devName, sizeof(devName), "DS/%s", device);
+-    ast_device_state_changed_literal(devName);
++    ast_device_state_changed_literal(devName, NULL, NULL);
+     ast_module_user_remove(u);
+     return 0;
+@@ -150,6 +158,8 @@ static int action_devstate(struct manses
+         const char *devstate = astman_get_header(m, "Devstate");
+         const char *value = astman_get_header(m, "Value");
+       const char *id = astman_get_header(m,"ActionID");
++        const char *cid_num = astman_get_header(m, "CallerID");
++        const char *cid_name = astman_get_header(m, "CallerIDName");
+       char devName[128];
+       char idText[256] = "";
+@@ -166,7 +176,7 @@ static int action_devstate(struct manses
+         if (!ast_db_put("DEVSTATES", devstate, (char *)value)) {
+           snprintf(devName, sizeof(devName), "DS/%s", devstate);
+-          ast_device_state_changed_literal(devName);
++          ast_device_state_changed_literal(devName, cid_num, cid_name);
+           astman_append(s, "Response: Success\r\n%s\r\n", idText);
+       } else {
+           ast_log(LOG_DEBUG, "ast_db_put failed\n");
+--- a/res/res_esel.c
++++ b/res/res_esel.c
+@@ -51,6 +51,8 @@ typedef struct esel_extension_state {
+     char context[AST_MAX_EXTENSION];
+     char exten[AST_MAX_EXTENSION];
+     int state;
++    char cid_num[AST_MAX_EXTENSION];
++    char cid_name[AST_MAX_EXTENSION];
+     char devstate[AST_MAX_EXTENSION];
+     struct esel_extension_state *next;
+     struct esel_extension_state *prev;
+@@ -93,7 +95,7 @@ typedef struct esel_pvt {
+ static struct esel_pvt *donkeys = NULL;
+-static int esel_queue_extension_state(struct esel_queue *queue, char *context, char *exten, int state, void *data) {
++static int esel_queue_extension_state(struct esel_queue *queue, char *context, char *exten, int state, void *data, char *cid_num, char *cid_name) {
+       struct esel_extension_state *exstate = NULL;
+       exstate = malloc(sizeof(struct esel_extension_state));
+@@ -115,6 +117,8 @@ static int esel_queue_extension_state(st
+       }
+       ast_copy_string(exstate->exten, exten, sizeof(exstate->exten));
+       ast_copy_string(exstate->context, context, sizeof(exstate->context));
++      ast_copy_string(exstate->cid_num, cid_num, sizeof(exstate->cid_num));
++      ast_copy_string(exstate->cid_name, cid_name, sizeof(exstate->cid_name));
+       exstate->state = state;
+       if (!queue->head) {
+               /* Empty queue */
+@@ -161,7 +165,7 @@ static void esel_export_to_remote(struct
+     char msg[1024];
+     int sent = 0;
+     memset(msg, 0x0, sizeof(msg));
+-    snprintf(msg, sizeof(msg) - 1, "Action: Devstate\r\nDevstate: %s\r\nValue: %d\r\n\r\n", exstate->devstate, esel_state2devstate(exstate->state));
++    snprintf(msg, sizeof(msg) - 1, "Action: Devstate\r\nDevstate: %s\r\nValue: %d\r\nCallerID: %s\r\nCallerIDName: %s\r\n\r\n", exstate->devstate, esel_state2devstate(exstate->state), exstate->cid_num, exstate->cid_name);
+     sent = send(esel->sockfd, msg, strlen(msg), 0);
+     if (sent == -1) {
+       esel->connected = 0;
+@@ -250,13 +254,13 @@ static void *do_esel_thread(void *data) 
+     return NULL;
+ }
+-static int esel_state_cb(char *context, char *exten, int state, void *data) {
++static int esel_state_cb(char *context, char *exten, int state, void *data, char *cid_num, char *cid_name) {
+       struct esel_pvt *esel;
+       esel = donkeys;
+         ast_mutex_lock(&listlock);
+       while (esel) {
+-          esel_queue_extension_state(&esel->queue, context, exten, state, data);
++          esel_queue_extension_state(&esel->queue, context, exten, state, data, cid_num, cid_name);
+           esel = esel->next;
+       }
+         ast_mutex_unlock(&listlock);
+Add or convert channel operations so they can use the unique ID.
+
+--- a/include/asterisk/channel.h
++++ b/include/asterisk/channel.h
+@@ -682,6 +682,18 @@ void  ast_channel_free(struct ast_channe
+  */
+ struct ast_channel *ast_request(const char *type, int format, void *data, int *status);
++/*! \brief Requests a channel
++ * \param type type of channel to request
++ * \param format requested channel format (codec)
++ * \param data data to pass to the channel requester
++ * \param status status
++ * \param uniqueid uniqueid
++ * Request a channel of a given type, with data as optional information used
++ * by the low level module. Sets the channels uniqueid to 'uniqueid'.
++ * \return Returns an ast_channel on success, NULL on failure.
++ */
++struct ast_channel *ast_request_with_uniqueid(const char *type, int format, void *data, int *status, char *uniqueid);
++
+ /*!
+  * \brief Request a channel of a given type, with data as optional information used 
+  * by the low level module and attempt to place a call on it
+@@ -697,8 +709,12 @@ struct ast_channel *ast_request(const ch
+  */
+ struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, const char *cidnum, const char *cidname);
++struct ast_channel *ast_request_and_dial_uniqueid(const char *type, int format, void *data, int timeout, int *reason, int callingpres, const char *cidnum, const char *cidname, char *uniqueid);
++
+ struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, const char *cidnum, const char *cidname, struct outgoing_helper *oh);
++struct ast_channel *__ast_request_and_dial_uniqueid(const char *type, int format, void *data, int timeout, int *reason, int callingpres, const char *cidnum, const char *cidname, struct outgoing_helper *oh, char *uniqueid);
++
+ /*! \brief "Requests" a channel for sending a message
+  * \param type type of channel to request
+  * \param data data to pass to the channel requester
+@@ -990,6 +1006,8 @@ struct ast_channel *ast_get_channel_by_e
+ /*! \brief Get next channel by exten (and optionally context) and lock it */
+ struct ast_channel *ast_walk_channel_by_exten_locked(const struct ast_channel *chan, const char *exten,
+                                                    const char *context);
++/*! Get channel by uniqueid (locks channel) */
++struct ast_channel *ast_get_channel_by_uniqueid_locked(const char *uniqueid);
+ /*! ! \brief Waits for a digit
+  * \param c channel to wait for a digit on
+--- a/main/channel.c
++++ b/main/channel.c
+@@ -1017,7 +1017,7 @@ void ast_channel_undefer_dtmf(struct ast
+  */
+ static struct ast_channel *channel_find_locked(const struct ast_channel *prev,
+                                              const char *name, const int namelen,
+-                                             const char *context, const char *exten)
++                                             const char *context, const char *exten, const char *uniqueid)
+ {
+       const char *msg = prev ? "deadlock" : "initial deadlock";
+       int retries;
+@@ -1045,7 +1045,10 @@ static struct ast_channel *channel_find_
+                                * XXX Need a better explanation for this ...
+                                */
+                       }
+-                      if (name) { /* want match by name */
++                      if (uniqueid) {
++                          if (!strcasecmp(c->uniqueid, uniqueid))
++                              break;
++                      } else if (name) { /* want match by name */
+                               if ((!namelen && strcasecmp(c->name, name)) ||
+                                   (namelen && strncasecmp(c->name, name, namelen)))
+                                       continue;       /* name match failed */
+@@ -1100,39 +1103,44 @@ static struct ast_channel *channel_find_
+ /*! \brief Browse channels in use */
+ struct ast_channel *ast_channel_walk_locked(const struct ast_channel *prev)
+ {
+-      return channel_find_locked(prev, NULL, 0, NULL, NULL);
++      return channel_find_locked(prev, NULL, 0, NULL, NULL, NULL);
+ }
+ /*! \brief Get channel by name and lock it */
+ struct ast_channel *ast_get_channel_by_name_locked(const char *name)
+ {
+-      return channel_find_locked(NULL, name, 0, NULL, NULL);
++      return channel_find_locked(NULL, name, 0, NULL, NULL, NULL);
+ }
+ /*! \brief Get channel by name prefix and lock it */
+ struct ast_channel *ast_get_channel_by_name_prefix_locked(const char *name, const int namelen)
+ {
+-      return channel_find_locked(NULL, name, namelen, NULL, NULL);
++      return channel_find_locked(NULL, name, namelen, NULL, NULL, NULL);
+ }
+ /*! \brief Get next channel by name prefix and lock it */
+ struct ast_channel *ast_walk_channel_by_name_prefix_locked(const struct ast_channel *chan, const char *name,
+                                                          const int namelen)
+ {
+-      return channel_find_locked(chan, name, namelen, NULL, NULL);
++      return channel_find_locked(chan, name, namelen, NULL, NULL, NULL);
+ }
+ /*! \brief Get channel by exten (and optionally context) and lock it */
+ struct ast_channel *ast_get_channel_by_exten_locked(const char *exten, const char *context)
+ {
+-      return channel_find_locked(NULL, NULL, 0, context, exten);
++      return channel_find_locked(NULL, NULL, 0, context, exten, NULL);
+ }
+ /*! \brief Get next channel by exten (and optionally context) and lock it */
+ struct ast_channel *ast_walk_channel_by_exten_locked(const struct ast_channel *chan, const char *exten,
+                                                    const char *context)
+ {
+-      return channel_find_locked(chan, NULL, 0, context, exten);
++      return channel_find_locked(chan, NULL, 0, context, exten, NULL);
++}
++
++struct ast_channel *ast_get_channel_by_uniqueid_locked(const char *uniqueid)
++{
++      return channel_find_locked(NULL, NULL, 0, NULL, NULL, uniqueid);
+ }
+ /*! \brief Wait, look for hangups and condition arg */
+@@ -2862,6 +2870,12 @@ char *ast_channel_reason2str(int reason)
+ struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, struct outgoing_helper *oh)
+ {
++      return __ast_request_and_dial_uniqueid(type, format, data,
++              timeout, outstate, 0, cid_num, cid_name, oh, NULL);
++}
++
++struct ast_channel *__ast_request_and_dial_uniqueid(const char *type, int format, void *data, int timeout, int *outstate, int callingpres, const char *cid_num, const char *cid_name, struct outgoing_helper *oh, char* uniqueid)
++{
+       int dummy_outstate;
+       int cause = 0;
+       struct ast_channel *chan;
+@@ -2873,7 +2887,7 @@ struct ast_channel *__ast_request_and_di
+       else
+               outstate = &dummy_outstate;     /* make outstate always a valid pointer */
+-      chan = ast_request(type, format, data, &cause);
++      chan = ast_request_with_uniqueid(type, format, data, &cause, uniqueid);
+       if (!chan) {
+               ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
+               /* compute error and return */
+@@ -2993,8 +3007,12 @@ struct ast_channel *ast_request_and_dial
+ {
+       return __ast_request_and_dial(type, format, data, timeout, outstate, cidnum, cidname, NULL);
+ }
++struct ast_channel *ast_request_and_dial_uniqueid(const char *type, int format, void *data, int timeout, int *outstate, int callingpres, const char *cidnum, const char *cidname, char *uniqueid)
++{
++      return __ast_request_and_dial_uniqueid(type, format, data, timeout, outstate, 0, cidnum, cidname, NULL, uniqueid);
++}
+-struct ast_channel *ast_request(const char *type, int format, void *data, int *cause)
++struct ast_channel *ast_request_with_uniqueid(const char *type, int format, void *data, int *cause, char *uniqueid)
+ {
+       struct chanlist *chan;
+       struct ast_channel *c;
+@@ -3033,6 +3051,7 @@ struct ast_channel *ast_request(const ch
+               if (!(c = chan->tech->requester(type, capabilities | videoformat, data, cause)))
+                       return NULL;
++              if (uniqueid) strncpy(c->uniqueid, uniqueid, sizeof(c->uniqueid));
+               /* no need to generate a Newchannel event here; it is done in the channel_alloc call */
+               return c;
+       }
+@@ -3044,6 +3063,11 @@ struct ast_channel *ast_request(const ch
+       return NULL;
+ }
++struct ast_channel *ast_request(const char *type, int format, void *data, int *cause)
++{
++    return ast_request_with_uniqueid(type, format, data, cause, NULL);
++}
++
+ int ast_call(struct ast_channel *chan, char *addr, int timeout)
+ {
+       /* Place an outgoing call, but don't wait any longer than timeout ms before returning.
+--- a/include/asterisk/pbx.h
++++ b/include/asterisk/pbx.h
+@@ -717,9 +717,17 @@ int ast_async_goto_by_name(const char *c
+ int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel);
+ /*! Synchronously or asynchronously make an outbound call and send it to a
++   particular extension (extended version with callinpres and uniqueid) */
++int ast_pbx_outgoing_exten_uniqueid(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, char *uniqueid);
++
++/*! Synchronously or asynchronously make an outbound call and send it to a
+    particular application with given extension */
+ int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel);
++/*! Synchronously or asynchronously make an outbound call and send it to a
++   particular application with given extension (extended version with callinpres and uniqueid) */
++int ast_pbx_outgoing_app_uniqueid(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, char *uniqueid);
++
+ /*!
+  * \brief Evaluate a condition
+  *
+--- a/main/pbx.c
++++ b/main/pbx.c
+@@ -4992,7 +4992,7 @@ static int ast_pbx_outgoing_cdr_failed(v
+       return 0;  /* success */
+ }
+-int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel)
++int ast_pbx_outgoing_exten_uniqueid(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel, char *uniqueid)
+ {
+       struct ast_channel *chan;
+       struct async_stat *as;
+@@ -5002,7 +5002,7 @@ int ast_pbx_outgoing_exten(const char *t
+       if (sync) {
+               LOAD_OH(oh);
+-              chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
++              chan = __ast_request_and_dial_uniqueid(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
+               if (channel) {
+                       *channel = chan;
+                       if (chan)
+@@ -5094,7 +5094,7 @@ int ast_pbx_outgoing_exten(const char *t
+                       res = -1;
+                       goto outgoing_exten_cleanup;
+               }
+-              chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name);
++              chan = ast_request_and_dial_uniqueid(type, format, data, timeout, reason, callingpres, cid_num, cid_name, uniqueid);
+               if (channel) {
+                       *channel = chan;
+                       if (chan)
+@@ -5134,6 +5134,10 @@ outgoing_exten_cleanup:
+       return res;
+ }
++int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel)
++{
++    return ast_pbx_outgoing_exten_uniqueid(type, format, data, timeout, context, exten, priority, reason, sync, 0, cid_num, cid_name, vars, account, channel, NULL);
++}
+ struct app_tmp {
+       char app[256];
+       char data[256];
+@@ -5158,7 +5162,7 @@ static void *ast_pbx_run_app(void *data)
+       return NULL;
+ }
+-int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
++int ast_pbx_outgoing_app_uniqueid(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, char *uniqueid)
+ {
+       struct ast_channel *chan;
+       struct app_tmp *tmp;
+@@ -5177,7 +5181,7 @@ int ast_pbx_outgoing_app(const char *typ
+               goto outgoing_app_cleanup;
+       }
+       if (sync) {
+-              chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
++              chan = __ast_request_and_dial_uniqueid(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
+               if (chan) {
+                       if (!chan->cdr) { /* check if the channel already has a cdr record, if not give it one */
+                               chan->cdr = ast_cdr_alloc();   /* allocate a cdr for the channel */
+@@ -5259,7 +5263,7 @@ int ast_pbx_outgoing_app(const char *typ
+                       res = -1;
+                       goto outgoing_app_cleanup;
+               }
+-              chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
++              chan = __ast_request_and_dial_uniqueid(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
+               if (!chan) {
+                       free(as);
+                       res = -1;
+@@ -5299,6 +5303,10 @@ outgoing_app_cleanup:
+       return res;
+ }
++int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
++{
++    return ast_pbx_outgoing_app_uniqueid(type, format, data, timeout, app, appdata, reason, sync, 0, cid_num, cid_name, vars, account, locked_channel, NULL);
++}
+ void __ast_context_destroy(struct ast_context *con, const char *registrar)
+ {
+       struct ast_context *tmp, *tmpl=NULL;
+--- a/res/res_monitor.c
++++ b/res/res_monitor.c
+@@ -340,6 +340,11 @@ int ast_monitor_stop(struct ast_channel 
+                       result = ast_safe_system(tmp);
+                       if (result == -1)
+                               ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
++                      manager_event(EVENT_FLAG_CALL, "MonitorStopped",
++                                          "Channel: %s\r\n"
++                                          "Uniqueid: %s\r\n"
++                                          "Result: %d\r\n"
++                                      ,chan->name, chan->uniqueid, result);
+               }
+               
+               free(chan->monitor->format);
+@@ -518,18 +523,28 @@ static int start_monitor_action(struct m
+       const char *fname = astman_get_header(m, "File");
+       const char *format = astman_get_header(m, "Format");
+       const char *mix = astman_get_header(m, "Mix");
++      const char *uniqueid = astman_get_header(m, "Uniqueid");
+       const char *target_url = astman_get_header(m, "TargetURL");
+       const char *target_script = astman_get_header(m, "TargetScript");
+       char *d;
+       
+-      if (ast_strlen_zero(name)) {
+-              astman_send_error(s, m, "No channel specified");
++      if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
++              astman_send_error(s, m, "No channel/uniqueid specified");
++              return 0;
++      }
++
++      if (!ast_strlen_zero(uniqueid)) {
++          c = ast_get_channel_by_uniqueid_locked(uniqueid);
++          if (!c) {
++              astman_send_error(s, m, "No such uniqueid");
+               return 0;
+-      }
+-      c = ast_get_channel_by_name_locked(name);
+-      if (!c) {
++          }
++      } else {
++          c = ast_get_channel_by_name_locked(name);
++          if (!c) {
+               astman_send_error(s, m, "No such channel");
+               return 0;
++          }
+       }
+       if (ast_strlen_zero(fname)) {
+@@ -570,16 +585,30 @@ static int stop_monitor_action(struct ma
+ {
+       struct ast_channel *c = NULL;
+       const char *name = astman_get_header(m, "Channel");
++      const char *uniqueid = astman_get_header(m, "Uniqueid");
+       int res;
+       if (ast_strlen_zero(name)) {
+               astman_send_error(s, m, "No channel specified");
+               return 0;
+       }
+-      c = ast_get_channel_by_name_locked(name);
+-      if (!c) {
+-              astman_send_error(s, m, "No such channel");
++      if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
++              astman_send_error(s, m, "No channel/uniqueid specified");
++              return 0;
++      }
++      if (!ast_strlen_zero(uniqueid)) {
++          c = ast_get_channel_by_uniqueid_locked(uniqueid);
++          if (!c) {
++              astman_send_error(s, m, "No such uniqueid");
+               return 0;
++          }
++      } else {
++          c = ast_get_channel_by_name_locked(name);
++          if (!c) {
++              astman_send_error(s, m, "No such channel");
++              return 0;
++          }
+       }
++
+       res = ast_monitor_stop(c, 1);
+       ast_channel_unlock(c);
+       if (res) {
+--- a/apps/app_chanspy.c
++++ b/apps/app_chanspy.c
+@@ -57,6 +57,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revisi
+ static const char *tdesc = "Listen to a channel, and optionally whisper into it";
+ static const char *app_chan = "ChanSpy";
++static const char *app_chan_uniqueid = "ChanSpyChan";
+ static const char *desc_chan = 
+ "  ChanSpy([chanprefix][|options]): This application is used to listen to the\n"
+ "audio from an Asterisk channel. This includes the audio coming in and\n"
+@@ -87,6 +88,27 @@ static const char *desc_chan = 
+ "                    channel.\n"
+ ;
++static const char *desc_uniqueid =
++"  ChanSpyChan(uniqueid[|options]): This application is used to listen to the\n"
++"audio from an Asterisk channel. This includes the audio coming in and\n"
++"out of the channel being spied on. The 'uniqueid' parameter has to be specified,\n"
++"  While spying, the following actions may be performed:\n"
++"    - Dialing # cycles the volume level.\n"
++"  Options:\n"
++"    q             - Don't play a beep when beginning to spy on a channel, or speak the\n"
++"                    selected channel name.\n"
++"    r[(basename)] - Record the session to the monitor spool directory. An\n"
++"                    optional base for the filename may be specified. The\n"
++"                    default is 'chanspy'.\n"
++"    v([value])    - Adjust the initial volume in the range from -4 to 4. A\n"
++"                    negative value refers to a quieter setting.\n"
++"    w             - Enable 'whisper' mode, so the spying channel can talk to\n"
++"                    the spied-on channel.\n"
++"    W             - Enable 'private whisper' mode, so the spying channel can\n"
++"                    talk to the spied-on channel but cannot listen to that\n"
++"                    channel.\n"
++;
++
+ static const char *app_ext = "ExtenSpy";
+ static const char *desc_ext = 
+ "  ExtenSpy(exten[@context][|options]): This application is used to listen to the\n"
+@@ -456,7 +478,7 @@ static struct chanspy_ds *setup_chanspy_
+ static struct chanspy_ds *next_channel(struct ast_channel *chan,
+       const struct ast_channel *last, const char *spec,
+-      const char *exten, const char *context, struct chanspy_ds *chanspy_ds)
++      const char *exten, const char *context, struct chanspy_ds *chanspy_ds, const char *uniqueid)
+ {
+       struct ast_channel *this;
+@@ -465,6 +487,8 @@ redo:
+               this = ast_walk_channel_by_name_prefix_locked(last, spec, strlen(spec));
+       else if (exten)
+               this = ast_walk_channel_by_exten_locked(last, exten, context);
++      else if (uniqueid)
++              this = ast_get_channel_by_uniqueid_locked(uniqueid);
+       else
+               this = ast_channel_walk_locked(last);
+@@ -485,7 +509,7 @@ redo:
+ static int common_exec(struct ast_channel *chan, const struct ast_flags *flags,
+                      int volfactor, const int fd, const char *mygroup, const char *spec,
+-                     const char *exten, const char *context)
++                     const char *exten, const char *context, const char *uniqueid)
+ {
+       char nameprefix[AST_NAME_STRLEN];
+       char peer_name[AST_NAME_STRLEN + 5];
+@@ -530,11 +554,11 @@ static int common_exec(struct ast_channe
+               waitms = 100;
+               num_spyed_upon = 0;
+-              for (peer_chanspy_ds = next_channel(chan, prev, spec, exten, context, &chanspy_ds);
++              for (peer_chanspy_ds = next_channel(chan, prev, spec, exten, context, &chanspy_ds, NULL);
+                    peer_chanspy_ds;
+                        chanspy_ds_free(peer_chanspy_ds), prev = peer,
+                    peer_chanspy_ds = next_chanspy_ds ? next_chanspy_ds : 
+-                              next_channel(chan, prev, spec, exten, context, &chanspy_ds), next_chanspy_ds = NULL) {
++                              next_channel(chan, prev, spec, exten, context, &chanspy_ds, NULL), next_chanspy_ds = NULL) {
+                       const char *group;
+                       int igrp = !mygroup;
+                       char *groups[25];
+@@ -733,7 +757,7 @@ static int chanspy_exec(struct ast_chann
+               }
+       }
+-      res = common_exec(chan, &flags, volfactor, fd, mygroup, spec, NULL, NULL);
++      res = common_exec(chan, &flags, volfactor, fd, mygroup, spec, NULL, NULL, NULL);
+       if (fd)
+               close(fd);
+@@ -818,7 +842,7 @@ static int extenspy_exec(struct ast_chan
+               }
+       }
+-      res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, exten, context);
++      res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, exten, context, NULL);
+       if (fd)
+               close(fd);
+@@ -831,14 +855,100 @@ static int extenspy_exec(struct ast_chan
+       return res;
+ }
++static int chanspychan_exec(struct ast_channel *chan, void *data)
++{
++      struct ast_module_user *u;
++      char *options = NULL;
++      char *uniqueid = NULL;
++      char *argv[2];
++      char *mygroup = NULL;
++      char *recbase = NULL;
++      int fd = 0;
++      struct ast_flags flags;
++      int oldwf = 0;
++      int argc = 0;
++      int volfactor = 0;
++      int res;
++
++      data = ast_strdupa(data);
++
++      u = ast_module_user_add(chan);
++
++      if ((argc = ast_app_separate_args(data, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
++              uniqueid = argv[0];
++              if (argc > 1)
++                      options = argv[1];
++
++              if (ast_strlen_zero(uniqueid)) {
++                      ast_log(LOG_ERROR, "no uniqueid specified.\n");
++                      ast_module_user_remove(u);
++                      return -1;
++              }
++      }
++
++      if (options) {
++              char *opts[OPT_ARG_ARRAY_SIZE];
++
++              ast_app_parse_options(spy_opts, &flags, opts, options);
++              if (ast_test_flag(&flags, OPTION_GROUP))
++                      mygroup = opts[OPT_ARG_GROUP];
++
++              if (ast_test_flag(&flags, OPTION_RECORD) &&
++                  !(recbase = opts[OPT_ARG_RECORD]))
++                      recbase = "chanspy";
++
++              if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
++                      int vol;
++
++                      if ((sscanf(opts[OPT_ARG_VOLUME], "%d", &vol) != 1) || (vol > 4) || (vol < -4))
++                              ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
++                      else
++                              volfactor = vol;
++              }
++
++              if (ast_test_flag(&flags, OPTION_PRIVATE))
++                      ast_set_flag(&flags, OPTION_WHISPER);
++      }
++
++      oldwf = chan->writeformat;
++      if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
++              ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
++              ast_module_user_remove(u);
++              return -1;
++      }
++
++      if (recbase) {
++              char filename[512];
++
++              snprintf(filename, sizeof(filename), "%s/%s.%d.raw", ast_config_AST_MONITOR_DIR, recbase, (int) time(NULL));
++              if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644)) <= 0) {
++                      ast_log(LOG_WARNING, "Cannot open '%s' for recording\n", filename);
++                      fd = 0;
++              }
++      }
++
++      res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, NULL, NULL, uniqueid);
++
++      if (fd)
++              close(fd);
++
++      if (oldwf && ast_set_write_format(chan, oldwf) < 0)
++              ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
++
++      ast_module_user_remove(u);
++
++      return res;
++}
++
++
+ static int unload_module(void)
+ {
+       int res = 0;
+       res |= ast_unregister_application(app_chan);
++      res |= ast_unregister_application(app_chan_uniqueid);
+       res |= ast_unregister_application(app_ext);
+-      ast_module_user_hangup_all();
+       return res;
+ }
+@@ -849,6 +959,7 @@ static int load_module(void)
+       res |= ast_register_application(app_chan, chanspy_exec, tdesc, desc_chan);
+       res |= ast_register_application(app_ext, extenspy_exec, tdesc, desc_ext);
++      res |= ast_register_application(app_chan_uniqueid, chanspychan_exec, tdesc, desc_uniqueid);
+       return res;
+ }
+--- a/main/manager.c
++++ b/main/manager.c
+@@ -87,6 +87,8 @@ struct fast_originate_helper {
+       char idtext[AST_MAX_EXTENSION];
+       char account[AST_MAX_ACCOUNT_CODE];
+       int priority;
++      int callingpres;
++      char uniqueid[64];
+       struct ast_variable *vars;
+ };
+@@ -1416,11 +1418,20 @@ static int action_hangup(struct mansessi
+ {
+       struct ast_channel *c = NULL;
+       const char *name = astman_get_header(m, "Channel");
+-      if (ast_strlen_zero(name)) {
+-              astman_send_error(s, m, "No channel specified");
++      const char *uniqueid = astman_get_header(m, "Uniqueid");
++
++      if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
++              astman_send_error(s, m, "No channel or uniqueid specified");
+               return 0;
+       }
+-      c = ast_get_channel_by_name_locked(name);
++
++      if (!ast_strlen_zero(uniqueid)) {
++              c = ast_get_channel_by_uniqueid_locked(uniqueid);
++      } else {
++          if (!ast_strlen_zero(name))
++              c = ast_get_channel_by_name_locked(name);
++      }
++
+       if (!c) {
+               astman_send_error(s, m, "No such channel");
+               return 0;
+@@ -1671,12 +1682,18 @@ static int action_redirect(struct manses
+       const char *exten = astman_get_header(m, "Exten");
+       const char *context = astman_get_header(m, "Context");
+       const char *priority = astman_get_header(m, "Priority");
++      const char *uniqueid = astman_get_header(m, "Uniqueid");
++      const char *uniqueid2 = astman_get_header(m, "ExtraUniqueid");
++      const char *exten2 = astman_get_header(m, "ExtraExten");
++      const char *context2 = astman_get_header(m, "ExtraContext");
++      const char *priority2 = astman_get_header(m, "ExtraPriority");
+       struct ast_channel *chan, *chan2 = NULL;
+       int pi = 0;
++      int pi2 = 0;
+       int res;
+-      if (ast_strlen_zero(name)) {
+-              astman_send_error(s, m, "Channel not specified");
++      if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
++              astman_send_error(s, m, "Channel or Uniqueid not specified");
+               return 0;
+       }
+       if (!ast_strlen_zero(priority) && (sscanf(priority, "%d", &pi) != 1)) {
+@@ -1685,8 +1702,18 @@ static int action_redirect(struct manses
+                       return 0;
+               }
+       }
++      if (!ast_strlen_zero(priority2) && (sscanf(priority2, "%d", &pi2) != 1)) {
++              if ((pi = ast_findlabel_extension(NULL, context2, exten2, priority2, NULL)) < 1) {
++                      astman_send_error(s, m, "Invalid extra priority\n");
++                      return 0;
++              }
++      }
+       /* XXX watch out, possible deadlock!!! */
+-      chan = ast_get_channel_by_name_locked(name);
++      if (!ast_strlen_zero(uniqueid)) {
++          chan = ast_get_channel_by_uniqueid_locked(uniqueid);
++      } else {
++          chan = ast_get_channel_by_name_locked(name);
++      }
+       if (!chan) {
+               char buf[BUFSIZ];
+               snprintf(buf, sizeof(buf), "Channel does not exist: %s", name);
+@@ -1698,8 +1725,11 @@ static int action_redirect(struct manses
+               ast_channel_unlock(chan);
+               return 0;
+       }
+-      if (!ast_strlen_zero(name2))
++      if (!ast_strlen_zero(uniqueid2)) {
++          chan2 = ast_get_channel_by_uniqueid_locked(uniqueid2);
++      } else if (!ast_strlen_zero(name2)) {
+               chan2 = ast_get_channel_by_name_locked(name2);
++      }
+       if (chan2 && ast_check_hangup(chan2)) {
+               astman_send_error(s, m, "Redirect failed, extra channel not up.\n");
+               ast_channel_unlock(chan);
+@@ -1708,9 +1738,9 @@ static int action_redirect(struct manses
+       }
+       res = ast_async_goto(chan, context, exten, pi);
+       if (!res) {
+-              if (!ast_strlen_zero(name2)) {
++              if ((!ast_strlen_zero(name2)) || (!ast_strlen_zero(uniqueid2))){
+                       if (chan2)
+-                              res = ast_async_goto(chan2, context, exten, pi);
++                              res = ast_async_goto(chan2, context2, exten2, pi2);
+                       else
+                               res = -1;
+                       if (!res)
+@@ -1789,15 +1819,15 @@ static void *fast_originate(void *data)
+       char requested_channel[AST_CHANNEL_NAME];
+       if (!ast_strlen_zero(in->app)) {
+-              res = ast_pbx_outgoing_app(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->app, in->appdata, &reason, 1, 
++              res = ast_pbx_outgoing_app_uniqueid(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->app, in->appdata, &reason, 1, in->callingpres,
+                       S_OR(in->cid_num, NULL), 
+                       S_OR(in->cid_name, NULL),
+-                      in->vars, in->account, &chan);
++                      in->vars, in->account, &chan, in->uniqueid);
+       } else {
+-              res = ast_pbx_outgoing_exten(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1, 
++              res = ast_pbx_outgoing_exten_uniqueid(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1, in->callingpres,
+                       S_OR(in->cid_num, NULL), 
+                       S_OR(in->cid_name, NULL),
+-                      in->vars, in->account, &chan);
++                      in->vars, in->account, &chan, in->uniqueid);
+       }
+       if (!chan)
+@@ -1857,6 +1887,7 @@ static int action_originate(struct manse
+       const char *appdata = astman_get_header(m, "Data");
+       const char *async = astman_get_header(m, "Async");
+       const char *id = astman_get_header(m, "ActionID");
++      const char *callingpres = astman_get_header(m, "CallingPres");
+       struct ast_variable *vars = astman_get_variables(m);
+       char *tech, *data;
+       char *l = NULL, *n = NULL;
+@@ -1866,6 +1897,9 @@ static int action_originate(struct manse
+       int reason = 0;
+       char tmp[256];
+       char tmp2[256];
++      char *uniqueid;
++      int cpresi = 0;
++      char idText[256] = "";
+       
+       pthread_t th;
+       pthread_attr_t attr;
+@@ -1883,6 +1917,10 @@ static int action_originate(struct manse
+               astman_send_error(s, m, "Invalid timeout\n");
+               return 0;
+       }
++      if (!ast_strlen_zero(callingpres) && (sscanf(callingpres, "%d", &cpresi) != 1)) {
++              astman_send_error(s, m, "Invalid CallingPres\n");
++              return 0;
++      }
+       ast_copy_string(tmp, name, sizeof(tmp));
+       tech = tmp;
+       data = strchr(tmp, '/');
+@@ -1902,6 +1940,7 @@ static int action_originate(struct manse
+               if (ast_strlen_zero(l))
+                       l = NULL;
+       }
++      uniqueid = ast_alloc_uniqueid();
+       if (ast_true(async)) {
+               struct fast_originate_helper *fast = ast_calloc(1, sizeof(*fast));
+               if (!fast) {
+@@ -1921,8 +1960,10 @@ static int action_originate(struct manse
+                       ast_copy_string(fast->context, context, sizeof(fast->context));
+                       ast_copy_string(fast->exten, exten, sizeof(fast->exten));
+                       ast_copy_string(fast->account, account, sizeof(fast->account));
++                      ast_copy_string(fast->uniqueid, uniqueid, sizeof(fast->uniqueid));
+                       fast->timeout = to;
+                       fast->priority = pi;
++                      fast->callingpres = cpresi;
+                       pthread_attr_init(&attr);
+                       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+                       if (ast_pthread_create(&th, &attr, fast_originate, fast)) {
+@@ -1933,19 +1974,28 @@ static int action_originate(struct manse
+                       pthread_attr_destroy(&attr);
+               }
+       } else if (!ast_strlen_zero(app)) {
+-              res = ast_pbx_outgoing_app(tech, AST_FORMAT_SLINEAR, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL);
++              res = ast_pbx_outgoing_app_uniqueid(tech, AST_FORMAT_SLINEAR, data, to, app, appdata, &reason, 1, cpresi, l, n, vars, account, NULL, uniqueid);
+       } else {
+               if (exten && context && pi)
+-                      res = ast_pbx_outgoing_exten(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL);
++                      res = ast_pbx_outgoing_exten_uniqueid(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 1, cpresi, l, n, vars, account, NULL, uniqueid);
+               else {
+                       astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
+                       return 0;
+               }
+       }   
+-      if (!res)
+-              astman_send_ack(s, m, "Originate successfully queued");
+-      else
++      if (!res) {
++              if (id && !ast_strlen_zero(id)) {
++                          snprintf(idText,256,"ActionID: %s\r\n",id);
++              }
++              ast_cli(s->fd, "Response: Success\r\n"
++                                  "%s"
++                                 "Message: Originate successfully queued\r\n"
++                                 "Uniqueid: %s\r\n"
++                                 "\r\n",
++                                  idText, uniqueid);
++      } else {
+               astman_send_error(s, m, "Originate failed");
++      }
+       return 0;
+ }
+--- a/include/asterisk/channel.h
++++ b/include/asterisk/channel.h
+@@ -89,6 +89,9 @@
+ #include "asterisk/abstract_jb.h"
++/* Max length of the uniqueid */
++#define AST_MAX_UNIQUEID 64
++
+ #include <unistd.h>
+ #ifdef POLLCOMPAT 
+ #include "asterisk/poll-compat.h"
+@@ -1039,6 +1042,8 @@ int ast_waitfordigit_full(struct ast_cha
+ int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders);
+ int ast_readstring_full(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders, int audiofd, int ctrlfd);
++char *ast_alloc_uniqueid(void);
++
+ /*! \brief Report DTMF on channel 0 */
+ #define AST_BRIDGE_DTMF_CHANNEL_0             (1 << 0)                
+ /*! \brief Report DTMF on channel 1 */
+--- a/main/channel.c
++++ b/main/channel.c
+@@ -706,6 +706,15 @@ static const struct ast_channel_tech nul
+       .description = "Null channel (should not see this)",
+ };
++/*! \brief Create a uniqueid */
++char *ast_alloc_uniqueid(void) {
++   char *uniqueid;
++   uniqueid = malloc(64);
++   if (!uniqueid) return NULL;
++   snprintf(uniqueid, 63, "%s-%d-%li.%d", ast_config_AST_SYSTEM_NAME, ast_mainpid, (long)time(NULL), ast_atomic_fetchadd_int(&uniqueint, 1));
++   return uniqueid;
++}
++
+ /*! \brief Create a new channel structure */
+ struct ast_channel *ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const int amaflag, const char *name_fmt, ...)
+ {
+--- a/include/asterisk/features.h
++++ b/include/asterisk/features.h
+@@ -47,6 +47,8 @@ struct ast_call_feature {
+ };
  
-                                                       ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-@@ -8928,6 +9341,16 @@ static void *pri_dchannel(void *vpri)
-                                                       if (!ast_strlen_zero(e->ring.callingsubaddr)) {
-                                                               pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
-                                                       }
-+                                                      if (!ast_strlen_zero(e->ring.callingnum)) {
-+                                                          char tmpstr[256];
-+                                                          pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingnum, sizeof(e->ring.callingnum), e->ring.callingplan, e->ring.callingpres, 0);
-+                                                          pbx_builtin_setvar_helper(c, "PRI_NETWORK_CID", tmpstr);
-+                                                      }
-+                                                      if (!ast_strlen_zero(e->ring.callingani)) {
-+                                                          char tmpstr[256];
-+                                                          pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingani, sizeof(e->ring.callingani), e->ring.callingplanuser, e->ring.callingpresuser, 0);
-+                                                          pbx_builtin_setvar_helper(c, "PRI_USER_CID", tmpstr);
-+                                                      }
-                                                       if (e->ring.ani2 >= 0) {
-                                                               snprintf(ani2str, 5, "%.2d", e->ring.ani2);
-                                                               pbx_builtin_setvar_helper(c, "ANI2", ani2str);
-@@ -8951,8 +9374,8 @@ static void *pri_dchannel(void *vpri)
-                                                       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-                                                       if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
-                                                               if (option_verbose > 2)
--                                                                      ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
--                                                                              plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
-+                                                                      ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap %s call from '%s' to '%s' on channel %d/%d, span %d\n",
-+                                                                              pri->pvts[chanpos]->digital ? "data" : "voice", plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
-                                                                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
-                                                       } else {
-                                                               ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 
-@@ -8960,15 +9383,19 @@ static void *pri_dchannel(void *vpri)
-                                                               if (c)
-                                                                       ast_hangup(c);
-                                                               else {
--                                                                      pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
-+                                                                      pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION, -1);
-                                                                       pri->pvts[chanpos]->call = NULL;
-                                                               }
-                                                       }
-                                                       pthread_attr_destroy(&attr);
-                                               } else  {
-+                                                      /* overlapdial = no */    
-                                                       ast_mutex_unlock(&pri->lock);
-                                                       /* Release PRI lock while we create the channel */
-                                                       c = zt_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
-+                                                      if (c && (e->ring.lowlayercompat[0] > 0)) {
-+                                                          memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
-+                                                      }
-                                                       if (c) {
-                                                               char calledtonstr[10];
  
-@@ -8995,26 +9422,43 @@ static void *pri_dchannel(void *vpri)
-                                                               ast_mutex_lock(&pri->lock);
++extern int ast_autoanswer_login(struct ast_channel *chan, void *data);
++extern int ast_masq_autoanswer_login(struct ast_channel *rchan, void *data);
  
-                                                               if (option_verbose > 2)
--                                                                      ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
--                                                                              plancallingnum, pri->pvts[chanpos]->exten, 
-+                                                                      ast_verbose(VERBOSE_PREFIX_3 "Accepting %s call from '%s' to '%s' on channel %d/%d, span %d\n",
-+                                                                              pri->pvts[chanpos]->digital ? "data" : "voice", e->ring.callingnum, pri->pvts[chanpos]->exten, 
-                                                                                       pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
-                                                               zt_enable_ec(pri->pvts[chanpos]);
-+                                                          if(!ast_strlen_zero(e->ring.callingsubaddr)) {
-+                                                              pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
-+                                                          }
-+                                                          if (!ast_strlen_zero(e->ring.callingnum)) {
-+                                                              char tmpstr[256];
-+                                                              pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingnum, sizeof(e->ring.callingnum), e->ring.callingplan, e->ring.callingpres, 0);
-+                                                              pbx_builtin_setvar_helper(c, "PRI_NETWORK_CID", tmpstr);
-+                                                          }
-+                                                          if (!ast_strlen_zero(e->ring.callingani)) {
-+                                                              char tmpstr[256];
-+                                                              pri_make_callerid(pri, tmpstr,sizeof(tmpstr),  e->ring.callingani, sizeof(e->ring.callingani), e->ring.callingplanuser, e->ring.callingpresuser, 0);
-+                                                              pbx_builtin_setvar_helper(c, "PRI_USER_CID", e->ring.callednum);
-+                                                          }
-+                                                          if (!ast_strlen_zero(e->ring.useruserinfo)) {
-+                                                              pbx_builtin_setvar_helper(c, "UUI", e->ring.useruserinfo);
-+                                                          }
-                                                       } else {
+ /*! \brief Park a call and read back parked location 
+  *  \param chan the channel to actually be parked
+--- a/res/res_features.c
++++ b/res/res_features.c
+@@ -11,6 +11,10 @@
+  * the project provides a web site, mailing lists and IRC
+  * channels for your use.
+  *
++ * Copyright (C) 2004, Junghanns.NET GmbH
++ *
++ * Klaus-Peter Junghanns <kpj@junghanns.net>
++ *
+  * This program is free software, distributed under the terms of
+  * the GNU General Public License Version 2. See the LICENSE file
+  * at the top of the source tree.
+@@ -132,6 +136,20 @@ static char *descrip2 = "Park():"
+ "it already exists. In that case, execution will continue at next\n"
+ "priority.\n" ;
  
-                                                               ast_mutex_lock(&pri->lock);
++static char *autoanswerlogin = "AutoanswerLogin";
++
++static char *synopsis3 = "Log in for autoanswer";
++
++static char *descrip3 = "AutoanswerLogin([context]|exten):"
++"Used to login to the autoanswer application for an extension.\n";
++
++static char *autoanswer = "Autoanswer";
++
++static char *synopsis4 = "Autoanswer a call";
++
++static char *descrip4 = "Autoanswer([context]|exten):"
++"Used to autoanswer a call for an extension.\n";
++
+ static struct ast_app *monitor_app = NULL;
+ static int monitor_ok = 1;
  
-                                                               ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 
-                                                                       pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
--                                                              pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
-+                                                              pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION, -1);
-                                                               pri->pvts[chanpos]->call = NULL;
-                                                       }
-                                               }
-                                       } else {
-+                                      /* invalid extension */
-                                               if (option_verbose > 2)
-                                                       ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist.  Rejecting call on channel %d/%d, span %d\n",
-                                                               pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 
-                                                                       pri->pvts[chanpos]->prioffset, pri->span);
--                                              pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
-+                                              pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED, -1);
-                                               pri->pvts[chanpos]->call = NULL;
-                                               pri->pvts[chanpos]->exten[0] = '\0';
-                                       }
-@@ -9023,9 +9467,9 @@ static void *pri_dchannel(void *vpri)
-                                       ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                               } else {
-                                       if (e->ring.flexible)
--                                              pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
-+                                              pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION, -1);
-                                       else
--                                              pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
-+                                              pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL, -1);
-                               }
-                               break;
-                       case PRI_EVENT_RINGING:
-@@ -9041,7 +9485,7 @@ static void *pri_dchannel(void *vpri)
-                                       } else {
-                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                               if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
--                                                      zt_enable_ec(pri->pvts[chanpos]);
-+                                              // XXX  zt_enable_ec(pri->pvts[chanpos]);
-                                                       pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
-                                                       pri->pvts[chanpos]->alerting = 1;
-                                               } else
-@@ -9073,9 +9517,16 @@ static void *pri_dchannel(void *vpri)
-                               }
-                               break;
-                       case PRI_EVENT_PROGRESS:
--                              /* Get chan value if e->e is not PRI_EVNT_RINGING */
-+                              /* Get chan value if e->e is not PRI_EVENT_RINGING */
-                               chanpos = pri_find_principle(pri, e->proceeding.channel);
-                               if (chanpos > -1) {
-+                                  if ((pri->pvts[chanpos]->priindication_oob == 2) && (e->proceeding.cause == PRI_CAUSE_USER_BUSY)) {
-+                                      /* received PROGRESS with cause BUSY, no inband callprogress wanted => hang up! */
-+                                      if (pri->pvts[chanpos]->owner) {
-+                                          pri->pvts[chanpos]->owner->hangupcause = AST_CAUSE_USER_BUSY;
-+                                          pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+                                      }
-+                                  } else {
- #ifdef PRI_PROGRESS_MASK
-                                       if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
- #else
-@@ -9122,6 +9573,12 @@ static void *pri_dchannel(void *vpri)
-                       case PRI_EVENT_PROCEEDING:
-                               chanpos = pri_find_principle(pri, e->proceeding.channel);
-                               if (chanpos > -1) {
-+                                  chanpos = pri_fixup_principle(pri, chanpos, e->proceeding.call);
-+                                  if (chanpos < 0) {
-+                                      ast_log(LOG_WARNING, "Received PROCEEDING on channel %d/%d not in use on span %d\n", 
-+                                              PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), pri->span);
-+                                      chanpos = -1;
-+                                  } else {
-                                       if (!pri->pvts[chanpos]->proceeding) {
-                                               struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
-                                               
-@@ -9169,6 +9626,295 @@ static void *pri_dchannel(void *vpri)
-                                       }
-                               }
-                               break;                          
-+                      case PRI_EVENT_SUSPEND_REQ:
-+                              if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
-+                                  pri_suspend_reject(pri->pri, e->suspend_req.call, "");
-+                                  break;
-+                              }
-+                              chanpos = pri_find_principle(pri, e->suspend_req.channel);
-+                              if (chanpos < 0)  {
-+                                      ast_log(LOG_WARNING, "Suspend requested on unconfigured channel %d span %d\n", chanpos, pri->span);
-+                                      chanpos = -1;
-+                              }
+@@ -150,6 +168,23 @@ struct parkeduser {
+       struct parkeduser *next;
+ };
++/* auto answer user */
++struct aauser {
++      struct ast_channel *chan;
++      struct timeval start;
++      /* waiting on this extension/context */
++      char exten[AST_MAX_EXTENSION];
++      char context[AST_MAX_EXTENSION];
++      int priority;
++      int notquiteyet;
++      struct aauser *next;
++};
++
++
++static struct aauser *aalot;
++AST_MUTEX_DEFINE_STATIC(autoanswer_lock);
++static pthread_t autoanswer_thread;
++
+ static struct parkeduser *parkinglot;
+ AST_MUTEX_DEFINE_STATIC(parking_lock);        /*!< protects all static variables above */
+@@ -405,11 +440,13 @@ static int park_call_full(struct ast_cha
+               "From: %s\r\n"
+               "Timeout: %ld\r\n"
+               "CallerID: %s\r\n"
+-              "CallerIDName: %s\r\n",
++              "CallerIDName: %s\r\n"
++              "Uniqueid: %s\r\n",
+               pu->parkingexten, pu->chan->name, peer ? peer->name : "",
+               (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
+               S_OR(pu->chan->cid.cid_num, "<unknown>"),
+-              S_OR(pu->chan->cid.cid_name, "<unknown>")
++              S_OR(pu->chan->cid.cid_name, "<unknown>"),
++              pu->chan->uniqueid
+               );
+       if (peer && adsipark && ast_adsi_available(peer)) {
+@@ -1656,11 +1693,13 @@ static void post_manager_event(const cha
+               "Exten: %s\r\n"
+               "Channel: %s\r\n"
+               "CallerID: %s\r\n"
+-              "CallerIDName: %s\r\n\r\n",
++              "CallerIDName: %s\r\n"
++              "Uniqueid: %s\r\n\r\n",
+               parkingexten, 
+               chan->name,
+               S_OR(chan->cid.cid_num, "<unknown>"),
+-              S_OR(chan->cid.cid_name, "<unknown>")
++              S_OR(chan->cid.cid_name, "<unknown>"),
++              chan->uniqueid
+               );
+ }
+@@ -1928,10 +1967,12 @@ static int park_exec(struct ast_channel 
+                       "Channel: %s\r\n"
+                       "From: %s\r\n"
+                       "CallerID: %s\r\n"
+-                      "CallerIDName: %s\r\n",
++                      "CallerIDName: %s\r\n"
++                      "Uniqueid: %s\r\n",
+                       pu->parkingexten, pu->chan->name, chan->name,
+                       S_OR(pu->chan->cid.cid_num, "<unknown>"),
+-                      S_OR(pu->chan->cid.cid_name, "<unknown>")
++                      S_OR(pu->chan->cid.cid_name, "<unknown>"),
++                      pu->chan->uniqueid
+                       );
+               free(pu);
+@@ -2085,15 +2126,10 @@ static struct ast_cli_entry cli_show_fea
+       handle_showfeatures, NULL,
+       NULL };
+-static struct ast_cli_entry cli_features[] = {
+-      { { "feature", "show", NULL },
+-      handle_showfeatures, "Lists configured features",
+-      showfeatures_help, NULL, &cli_show_features_deprecated },
++static char showautoanswer_help[] =
++"Usage: show autoanswer\n"
++"       Lists currently logged in autoanswer users.\n";
+-      { { "show", "parkedcalls", NULL },
+-      handle_parkedcalls, "Lists parked calls",
+-      showparked_help },
+-};
+ /*! \brief Dump lot status */
+ static int manager_parking_status( struct mansession *s, const struct message *m)
+@@ -2117,12 +2153,13 @@ static int manager_parking_status( struc
+                       "Timeout: %ld\r\n"
+                       "CallerID: %s\r\n"
+                       "CallerIDName: %s\r\n"
++                      "Uniqueid: %s\r\n\r\n"
+                       "%s"
+                       "\r\n",
+                       cur->parkingnum, cur->chan->name, cur->peername,
+                       (long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
+                       S_OR(cur->chan->cid.cid_num, ""),       /* XXX in other places it is <unknown> */
+-                      S_OR(cur->chan->cid.cid_name, ""),
++                      S_OR(cur->chan->cid.cid_name, ""), cur->chan->uniqueid,
+                       idText);
+       }
+@@ -2197,6 +2234,427 @@ static int manager_park(struct mansessio
+       return 0;
+ }
++static int handle_autoanswer(int fd, int argc, char *argv[])
++{
++      struct aauser *cur;
 +
-+                              if (chanpos > -1) {
-+                                  ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+                                  if (pri->pvts[chanpos]->owner) {
-+                                      if (ast_bridged_channel(pri->pvts[chanpos]->owner)) {
-+                                          struct zt_suspended_call *zpc;
-+                                          char tmpstr[256];
-+                                          zpc = malloc(sizeof(struct zt_suspended_call));
-+                                          if (!zpc) {
-+                                              ast_log(LOG_ERROR, "unable to malloc zt_suspended_call\n");
-+                                              break;
-+                                          }
-+                                          strncpy(zpc->msn,  pri->pvts[chanpos]->cid_num, sizeof(zpc->msn));
-+                                          strncpy(zpc->callid,  e->suspend_req.callid, sizeof(zpc->callid));
-+                                          ast_masq_park_call(ast_bridged_channel(pri->pvts[chanpos]->owner), NULL, 0, &zpc->parked_at);
-+                                          zpc->next = pri->suspended_calls;
-+                                          pri->suspended_calls = zpc;
-+                                          snprintf(tmpstr, sizeof(tmpstr), "Parked at %d", zpc->parked_at);
-+                                          pri_suspend_acknowledge(pri->pri, e->suspend_req.call,tmpstr);
-+                                          pri->pvts[chanpos]->call = NULL;
-+                                          pri->pvts[chanpos]->tei = -1;
-+                                          pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+                                      } else {
-+                                          pri_suspend_reject(pri->pri, e->suspend_req.call, "cant park a non-bridge");
-+                                          ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+                                          break;
-+                                      }
-+                                  } else {
-+                                      pri_suspend_reject(pri->pri, e->suspend_req.call, "");
-+                                  }
-+                                  ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+                              }
-+                              break;
-+                      case PRI_EVENT_RESUME_REQ:
-+                              if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
-+                                  break;
-+                              }
-+                              chanpos = pri_find_empty_chan(pri, 1);
-+                              if (chanpos < 0) { 
-+                                      pri_resume_reject(pri->pri, e->resume_req.call,"All channels busy");
-+                                      ast_log(LOG_WARNING, "Resume requested on odd channel number %d span %d\n", chanpos, pri->span);
-+                                      chanpos = -1;
-+                              } else if (!pri->pvts[chanpos]) {
-+                                      pri_resume_reject(pri->pri, e->resume_req.call,"General protection fault in module 0x0BRI");
-+                                      chanpos = -1;
-+                              }
++      ast_cli(fd, "%25s %10s %15s \n", "Channel"
++              , "Extension", "Context");
++
++      ast_mutex_lock(&autoanswer_lock);
++
++      cur=aalot;
++      while(cur) {
++              ast_cli(fd, "%25s %10s %15s\n",cur->chan->name, cur->exten, cur->context);
++
++              cur = cur->next;
++      }
++
++      ast_mutex_unlock(&autoanswer_lock);
++
++      return RESULT_SUCCESS;
++}
++
++static struct ast_cli_entry cli_features[] = {
++      { { "feature", "list", NULL },
++      handle_showfeatures, "Lists configured features",
++      showfeatures_help, NULL, &cli_show_features_deprecated },
++
++      { { "show", "parkedcalls", NULL },
++      handle_parkedcalls, "Lists parked calls",
++      showparked_help },
++
++      { { "show", "autoanswer", NULL },
++      handle_autoanswer, "Lists autoanswer users",
++      showautoanswer_help },
++};
++int ast_masq_autoanswer_login(struct ast_channel *rchan, void *data)
++{
++      struct ast_channel *chan;
++      struct ast_frame *f;
++      /* Make a new, fake channel that we'll use to masquerade in the real one */
++      chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Autoanswer/%s", rchan->name);
++      if (chan) {
++              /* Let us keep track of the channel name */
++              ast_string_field_build(chan, name, "Autoanswer/%s",rchan->name);
++              /* Make formats okay */
++              chan->readformat = rchan->readformat;
++              chan->writeformat = rchan->writeformat;
++              ast_channel_masquerade(chan, rchan);
++              /* Setup the extensions and such */
++              strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
++              strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
++              chan->priority = rchan->priority;
++              /* might be dirty but we want trackable channels */
++              ast_string_field_build(chan, uniqueid, "%s",rchan->uniqueid);
++              /* Make the masq execute */
++              f = ast_read(chan);
++              if (f)
++                      ast_frfree(f);
++              ast_autoanswer_login(chan, data);
++      } else {
++              ast_log(LOG_WARNING, "Unable to create aa channel\n");
++              return -1;
++      }
++      return 0;
++}
++
++static int autoanswer_login_exec(struct ast_channel *chan, void *data)
++{
++      int res=0;
++      struct ast_module_user *u;
++
++      u = ast_module_user_add(chan);
++      if (!data) {
++              ast_log(LOG_WARNING, "AutoanswerLogin requires an argument (extension number)\n");
++              return -1;
++      }
++      res = ast_masq_autoanswer_login(chan, data);
++      ast_module_user_remove(u);
++      return res;
++}
++
++int ast_autoanswer_login(struct ast_channel *chan, void *data)
++{
++      /* We put the user in the parking list, then wake up the parking thread to be sure it looks
++         after these channels too */
++      struct ast_context *con;
++      char exten[AST_MAX_EXTENSION];
++      struct aauser *pu,*pl = NULL;
++      char *s, *stringp, *aacontext, *aaexten = NULL;
++
++      s = ast_strdupa((void *) data);
++      stringp=s;
++      aacontext = strsep(&stringp, "|");
++      aaexten = strsep(&stringp, "|");
++      if (!aaexten) {
++          aaexten = aacontext;
++          aacontext = NULL;
++      }
++      if (!aaexten) {
++              ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
++              return -1;
++      } else {
++              if (!aacontext) {
++                      aacontext = "default";
++              }
++      }
++
++      ast_mutex_lock(&autoanswer_lock);
++      pu = aalot;
++      while(pu) {
++              if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
++                      if (pl)
++                              pl->next = pu->next;
++                      else
++                              aalot = pu->next;
++                      break;
++              }
++              pl = pu;
++              pu = pu->next;
++      }
++      ast_mutex_unlock(&autoanswer_lock);
++      if (pu) {
++          ast_log(LOG_NOTICE, "Logout old Channel %s for %s@%s.\n",pu->chan->name, pu->exten, pu->context);
++          manager_event(EVENT_FLAG_CALL, "AutoanswerLogout",
++                                          "Channel: %s\r\n"
++                                          "Uniqueid: %s\r\n"
++                                          "Context: %s\r\n"
++                                          "Exten: %s\r\n"
++                                      ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
++          ast_hangup(pu->chan);
++          free(pu);
++      }
++      pu = malloc(sizeof(struct aauser));
++      if (pu) {
++              memset(pu, 0, sizeof(pu));
++              ast_mutex_lock(&autoanswer_lock);
++              chan->appl = "Autoanswer";
++              chan->data = NULL;
++
++              pu->chan = chan;
++              if (chan->_state != AST_STATE_UP) {
++                  ast_answer(chan);
++              }
++
++              /* Start music on hold */
++              ast_moh_start(pu->chan, NULL, NULL);
++              gettimeofday(&pu->start, NULL);
++              strncpy(pu->exten, aaexten, sizeof(pu->exten)-1);
++              strncpy(pu->context, aacontext, sizeof(pu->exten)-1);
++              pu->next = aalot;
++              aalot = pu;
++              con = ast_context_find(aacontext);
++              if (!con) {
++                      con = ast_context_create(NULL,aacontext, registrar);
++                      if (!con) {
++                              ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", aacontext);
++                      }
++              }
++              if (con) {
++                      snprintf(exten, sizeof(exten), "%s", aaexten);
++                      ast_add_extension2(con, 1, exten, 1, NULL, NULL, autoanswer, strdup((char *)data), free, registrar);
++              }
++
++              ast_mutex_unlock(&autoanswer_lock);
++              /* Wake up the (presumably select()ing) thread */
++              pthread_kill(autoanswer_thread, SIGURG);
++              if (option_verbose > 1)
++                      ast_verbose(VERBOSE_PREFIX_2 "Autoanswer login from %s for %s@%s.\n", pu->chan->name, pu->exten, pu->context);
++                      manager_event(EVENT_FLAG_CALL, "AutoanswerLogin",
++                                "Channel: %s\r\n"
++                                "Uniqueid: %s\r\n"
++                              "Context: %s\r\n"
++                              "Exten: %s\r\n"
++                              ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
 +
-+                              if (chanpos > -1) {
-+                                  ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+                                  if (!pri->pvts[chanpos]->owner) {
-+                                      struct zt_suspended_call *zpc, *zpcl;
-+                                      int unparked=0;
-+                                      char extenstr[255], temp[255];
-+                                      zpc = NULL;
-+                                      zpcl = pri->suspended_calls;
-+                                      while (zpcl) {
-+                                      //    ast_log(LOG_NOTICE, "zpc->parked_at %d zpcl->callid %s\n",zpcl->parked_at, zpcl->callid);
-+                                          if (((strlen(zpcl->callid) == 0) && (strlen(e->resume_req.callid)==0)) || (!strcmp(zpcl->callid,e->resume_req.callid))) {
-+                                              int law;
-+                                              // found a parked call
-+                                              snprintf(extenstr, sizeof(extenstr), "%d", zpcl->parked_at);
-+                                              strncpy(pri->pvts[chanpos]->exten, extenstr, sizeof(pri->pvts[chanpos]->exten));
-+                                      //      strncpy(pri->pvts[chanpos]->context, ast_parking_con(), sizeof(pri->pvts[chanpos]->context));
-+                                              pri->pvts[chanpos]->call = e->resume_req.call;
-+                                              law = 1;
-+                                              if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1)
-+                                                  ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]), law);
-+                                      // uhh ohh...what shall we do without the bearer cap???
-+                                              law = ZT_LAW_ALAW;
-+                                              res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
-+                                              if (res < 0) 
-+                                                  ast_log(LOG_WARNING, "Unable to set law on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
-+                                              if (!pri->pvts[chanpos]->digital) {
-+                                                  res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
-+                                              } else {
-+                                                  res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[chanpos]->law);
-+                                              }
-+                                              if (res < 0)
-+                                                  ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
-+                                              /* Start PBX */
-+                                              c = zt_new(pri->pvts[chanpos], AST_STATE_UP, 1, SUB_REAL, law, PRI_TRANS_CAP_SPEECH);
-+                                              if (c) {
-+                                                  pri->pvts[chanpos]->owner = c;
-+                                                  pri->pvts[chanpos]->call = e->resume_req.call;
-+                                                  zt_enable_ec(pri->pvts[chanpos]);
-+                                                  zt_train_ec(pri->pvts[chanpos]);
-+                                              } else {
-+                                                  ast_log(LOG_ERROR, "unable to start pbx\n");
-+                                              }
++                      return 0;
++      } else {
++              ast_log(LOG_WARNING, "Out of memory\n");
++              return -1;
++      }
++      return 0;
++}
 +
-+                                              if (zpc) {
-+                                                  zpc->next = zpcl->next;
-+                                                  free(zpcl);
-+                                                  zpcl = zpc->next;
-+                                              } else {
-+                                                  // remove head
-+                                                  pri->suspended_calls = zpcl->next;
-+                                                  free(zpcl);
-+                                                  zpcl = pri->suspended_calls;
-+                                                  zpc = NULL;
-+                                              }
-+                                              unparked = 1;
-+                                              snprintf(temp, sizeof(temp), "Unparked %s", extenstr);
-+                                              pri_resume_acknowledge(pri->pri, e->resume_req.call, chanpos + 1, temp);
-+                                              break;
-+                                          }
-+                                          zpc = zpcl;
-+                                          if (zpcl) zpcl = zpcl->next;
-+                                      }
-+                                      if (!unparked)
-+                                          pri_resume_reject(pri->pri, e->resume_req.call,"No suspended call to unpark!");
-+                                  } else {
-+                                      pri_resume_reject(pri->pri, e->resume_req.call,"No suspended call to unpark!");
-+                                  }
-+                                  ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+                              }
-+                              break;
-+                      case PRI_EVENT_HOLD_REQ:
-+                              if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
-+                                  pri_hold_reject(pri->pri, e->hold_req.call);
-+                                  break;
-+                              }
-+                              chanpos = pri_find_principle(pri, e->hold_req.channel);
-+                              if (chanpos < 0)  {
-+                                      ast_log(LOG_WARNING, "Hold requested on unconfigured channel %d span %d\n", chanpos, pri->span);
-+                                      chanpos = -1;
-+                              }
-+                              if (chanpos > -1) {
-+                              //    ast_log(LOG_NOTICE, "Hold request for channel number %d span %d\n", chanpos, pri->span);
-+                                  ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+                                  if (pri->pvts[chanpos]->owner) {
-+                                      struct zt_pvt *p = pri->pvts[chanpos];
-+                                      struct zt_holded_call *zhc;
-+                                      int holdacked=0;
-+                                      
-+//                                    ast_log(LOG_NOTICE,"HOLD request from channel %s tei %d\n",p->owner->name, e->hold_req.tei);
-+                                      if (ast_bridged_channel(p->owner)) {
-+                                          zhc = malloc(sizeof(struct zt_holded_call));
-+                                          if (!zhc) {
-+                                              ast_log(LOG_ERROR, "unable to malloc zt_holded_call\n");
-+                                              break;
-+                                          }
-+                                          memset(zhc, 0, sizeof(zhc));
-+                                          strncpy(zhc->msn,  pri->pvts[chanpos]->cid_num, sizeof(zhc->msn));
-+                                          strncpy(zhc->uniqueid,  ast_bridged_channel(p->owner)->uniqueid, sizeof(zhc->uniqueid));
-+                                          zhc->tei = e->hold_req.tei;
-+                                          zhc->cref = e->hold_req.cref;
-+                                          zhc->call = e->hold_req.call;
-+                                          zhc->channel = p->owner;
-+                                          zhc->alreadyhungup = 0;
-+                                          zhc->bridge = ast_bridged_channel(p->owner);
-+                                          zhc->next = pri->holded_calls;
-+                                          pri->holded_calls = zhc;
-+
-+                                          /* put channel on hold */
-+                                          ast_masq_hold_call(ast_bridged_channel(p->owner), p->owner);
-+
-+                                          pri_hold_acknowledge(pri->pri, e->hold_req.call);
-+                                          holdacked = 1;
-+                                          p->call = NULL; // free the bchannel withouth destroying the call
-+                                          p->tei = -1;
-+                                      } else {
-+                                          // cant hold a non-bridge,...yet
-+                                          
-+                                          // make a fake channel
-+                                          
-+                                          // masquerade
-+                                          
-+                                          // put on hold
-+                                          pri_hold_reject(pri->pri, e->hold_req.call);
-+                                      }
-+                                  } else {
-+                                          pri_hold_reject(pri->pri, e->hold_req.call);
-+                                  }
-+                                  ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+                              } else {
-+                                      pri_hold_reject(pri->pri, e->hold_req.call);
-+                              }
-+                              break; 
-+                      case PRI_EVENT_RETRIEVE_REQ:
-+                              if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
-+                                  pri_retrieve_reject(pri->pri, e->retrieve_req.call);
-+                                  break;
-+                              }
-+                              chanpos = pri_find_empty_chan(pri, 1);
-+                              if (chanpos < 0) { 
-+                                      pri_retrieve_reject(pri->pri, e->retrieve_req.call);
-+                                      ast_log(LOG_WARNING, "Retrieve requested on odd channel number %d span %d\n", chanpos, pri->span);
-+                                      chanpos = -1;
-+                                      break;
-+                              } else if (!pri->pvts[chanpos]) {
-+                                      ast_log(LOG_WARNING, "Retrieve requested on unconfigured channel number %d span %d\n", chanpos, pri->span);
-+                                      pri_retrieve_reject(pri->pri, e->retrieve_req.call);
-+                                      chanpos = -1;
-+                                      break;
-+                              }
-+                              if (chanpos > -1) {
-+                                  struct zt_holded_call *onhold = NULL;
-+                                  int retrieved = 0;
-+                                  int res = -1;
-+                                  struct app_tmp *tmp;
-+                                  pthread_attr_t attr;
-+                                  int law;
-+
-+                                  onhold = pri_get_callonhold(pri, e->retrieve_req.cref, e->retrieve_req.tei);
-+
-+                                  if (!onhold) {
-+                                      pri_retrieve_reject(pri->pri, e->retrieve_req.call);
-+                                      break;
-+                                  }
-+                                  ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+                                      // found a parked call
-+                                      law = 1;
-+                                      if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1)
-+                                          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]), law);
-+                                      // uhh ohh...what shall we do without the bearer cap???
-+                                      law = ZT_LAW_ALAW;
-+                                      res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
-+                                      if (res < 0) 
-+                                          ast_log(LOG_WARNING, "Unable to set law on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
-+                                      res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
-+                                      if (res < 0)
-+                                          ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
-+                                      /* Start PBX */
-+                                      c = zt_new(pri->pvts[chanpos], AST_STATE_UP, 0, SUB_REAL, law, PRI_TRANS_CAP_SPEECH);
-+                                      if (c) {
-+                                          pri->pvts[chanpos]->owner = c;
-+                                          pri->pvts[chanpos]->outgoing = 1; /* for not sending proceedings... */
-+                                          pri->pvts[chanpos]->call = e->retrieve_req.call;
-+                                          pri->pvts[chanpos]->tei = e->retrieve_req.tei;
-+                                          zt_enable_ec(pri->pvts[chanpos]);
-+                                          zt_train_ec(pri->pvts[chanpos]);
-+                                      } else {
-+                                          ast_log(LOG_ERROR, "unable to start pbx\n");
-+                                      }
++static void autoanswer_reregister_extensions(void)
++{
++      struct aauser *cur;
++      struct ast_context *con;
++      char exten[AST_MAX_EXTENSION];
++      char args[AST_MAX_EXTENSION];
 +
-+                                      retrieved = 1;
-+                              //      ast_log(LOG_NOTICE, "sending RETRIEVE ACK on channel %d, span %d for tei %d cref %d\n",chanpos,pri->span, e->retrieve_req.tei,  e->retrieve_req.cref);
-+                                      pri_retrieve_acknowledge(pri->pri, e->retrieve_req.call, chanpos + 1);
-+
-+                                      // the magic begins here: ....
-+                                      tmp = malloc(sizeof(struct app_tmp));
-+                                      if (tmp) {
-+                                          memset(tmp, 0, sizeof(struct app_tmp));
-+                                          strncpy(tmp->app, "holdedcall", sizeof(tmp->app) - 1);
-+                                          strncpy(tmp->data, onhold->uniqueid, sizeof(tmp->data) - 1);
-+                                          tmp->chan = c;
-+                                      }
-+                                      pri_destroy_callonhold(pri, onhold);
-+                                      onhold = NULL;
-+
-+                                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+                                      pthread_attr_init(&attr);
-+                                      pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-+                                      if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) {
-+                                          ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", c->name, strerror(errno));
-+                                          free(tmp);
-+                                          ast_hangup(c);
-+                                          retrieved = 0;
-+                                      }
++      ast_mutex_lock(&autoanswer_lock);
 +
-+                                  if (!retrieved) {
-+                                      pri_retrieve_reject(pri->pri, e->retrieve_req.call);
-+                                  }
-+                              }
-+                              break; 
-+                      case PRI_EVENT_DISPLAY_RECEIVED:
-+                              ast_log(LOG_NOTICE, "DISPLAY IE: [ %s ] received\n",e->display.text);
-+                              chanpos = pri_find_principle(pri, e->display.channel);
-+                              if (chanpos < 0) {
-+                                  ast_log(LOG_WARNING, "odd channel number %d span %d\n", chanpos, pri->span);
-+                                  chanpos = -1;
-+                              } 
-+                              if (chanpos > -1) {
-+                                  if (pri->pvts[chanpos]->owner) {
-+                      //              ast_sendtext(pri->pvt[chanpos]->owner, e->display.text);
-+                                  }
-+                              }                               
-+                              break;
-                       case PRI_EVENT_ANSWER:
-                               chanpos = pri_find_principle(pri, e->answer.channel);
-                               if (chanpos < 0) {
-@@ -9181,6 +9927,7 @@ static void *pri_dchannel(void *vpri)
-                                                       PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
-                                       } else {
-                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+                                              pri->pvts[chanpos]->tei = e->answer.tei;
-                                               /* Now we can do call progress detection */
-                                               /* We changed this so it turns on the DSP no matter what... progress or no progress.
-@@ -9210,11 +9957,16 @@ static void *pri_dchannel(void *vpri)
-                                                               ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
-                                                       pri->pvts[chanpos]->dop.dialstr[0] = '\0';
-                                               } else if (pri->pvts[chanpos]->confirmanswer) {
--                                                      ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
-+                                                      ast_log(LOG_DEBUG, "Waiting for answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
-+                                                      enable_dtmf_detect(pri->pvts[chanpos]);
-                                               } else {
-+                                                      pri->pvts[chanpos]->dialing = 0;
-                                                       pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
-                                                       /* Enable echo cancellation if it's not on already */
-                                                       zt_enable_ec(pri->pvts[chanpos]);
-+                                                      zt_train_ec(pri->pvts[chanpos]);
-+                                                      /* stop ignoring inband dtmf */
-+                                                      enable_dtmf_detect(pri->pvts[chanpos]);
-                                               }
- #ifdef SUPPORT_USERUSER
-@@ -9271,20 +10023,29 @@ static void *pri_dchannel(void *vpri)
-                                                               ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n", 
-                                                                       pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
-                                               } else {
--                                                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
-+                                                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
-                                                       pri->pvts[chanpos]->call = NULL;
-+                                                      pri->pvts[chanpos]->tei = -1;
-                                               }
-                                               if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
--                                                      if (option_verbose > 2)
-+                                                      if ((pri->nodetype != BRI_CPE_PTMP) && (pri->nodetype != BRI_NETWORK_PTMP)) {
-+                                                          if (option_verbose > 2)
-                                                               ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 
--                                                                      PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
--                                                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
--                                                      pri->pvts[chanpos]->resetting = 1;
--                                              }
--                                              if (e->hangup.aoc_units > -1)
-+                                                                      PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-+                                                          pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
-+                                                          pri->pvts[chanpos]->resetting = 1;
-+                                                      }
-+                                              }
-+                                              if (e->hangup.aoc_units > -1) {
-+                                                      if (pri->pvts[chanpos]->owner) {
-+                                                          char tmpstr[256];
-+                                                          snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
-+                                                          pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
-+                                                      }
-                                                       if (option_verbose > 2)
-                                                               ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
-                                                                       pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
++      cur=aalot;
++      while(cur) {
++              con = ast_context_find(cur->context);
++              if (!con) {
++                      con = ast_context_create(NULL,cur->context, registrar);
++                      if (!con) {
++                              ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", cur->context);
++                      }
++              }
++              if (con) {
++                      snprintf(exten, sizeof(exten), "%s", cur->exten);
++                      snprintf(args, sizeof(args), "%s|%s", cur->context, cur->exten);
++                      ast_add_extension2(con, 1, exten, 1, NULL, NULL, autoanswer, strdup((char *)args), free, registrar);
++              }
++              cur = cur->next;
++      }
++
++      ast_mutex_unlock(&autoanswer_lock);
++}
++static void *do_autoanswer_thread(void *ignore)
++{
++      int ms, tms, max;
++      struct ast_context *con;
++      char exten[AST_MAX_EXTENSION];
++      struct aauser *pu, *pl, *pt = NULL;
++      struct timeval tv;
++      struct ast_frame *f;
++      int x;
++      fd_set rfds, efds;
++      fd_set nrfds, nefds;
++      FD_ZERO(&rfds);
++      FD_ZERO(&efds);
++      for (;;) {
++              ms = -1;
++              max = -1;
++              ast_mutex_lock(&autoanswer_lock);
++              pl = NULL;
++              pu = aalot;
++              gettimeofday(&tv, NULL);
++              FD_ZERO(&nrfds);
++              FD_ZERO(&nefds);
++              while(pu) {
++                      tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
++                      for (x=0;x<AST_MAX_FDS;x++) {
++                              if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
++                                      if (FD_ISSET(pu->chan->fds[x], &efds))
++                                              ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
++                                      else
++                                              ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
++                                      pu->chan->fdno = x;
++                                      /* See if they need servicing */
++                                      f = ast_read(pu->chan);
++                                      if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass ==  AST_CONTROL_HANGUP))) {
++                                              /* There's a problem, hang them up*/
++                                              if (option_verbose > 1)
++                                                      ast_verbose(VERBOSE_PREFIX_2 "%s logged out of autoanswer app\n", pu->chan->name);
++                                              manager_event(EVENT_FLAG_CALL, "AutoanswerLogout",
++                                                  "Channel: %s\r\n"
++                                                  "Uniqueid: %s\r\n"
++                                                  "Context: %s\r\n"
++                                                  "Exten: %s\r\n"
++                                              ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
++                                              ast_hangup(pu->chan);
++                                              con = ast_context_find(pu->context);
++                                              if (con) {
++                                                  snprintf(exten, sizeof(exten), "%s", pu->exten);
++                                                  if (ast_context_remove_extension2(con, exten, 1, registrar))
++                                                      ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
++                                              } else {
++                                                      ast_log(LOG_WARNING, "Whoa, no %s context?\n", pu->exten);
 +                                              }
- #ifdef SUPPORT_USERUSER
-                                               if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
-@@ -9297,8 +10058,20 @@ static void *pri_dchannel(void *vpri)
-                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                       } else {
--                                              ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 
--                                                      PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-+                                              struct zt_holded_call *onhold = NULL;
-+                                              /* check calls on hold */
-+                                              onhold = pri_get_callonhold(pri, e->hangup.cref, e->hangup.tei);
-+                                              
-+                                              if (onhold) {
-+                                                  // ast_log(LOG_NOTICE, "hangup, found cref %d, tei %d\n",e->hangup.cref, e->hangup.tei);
-+                                                  pri_hangup(pri->pri, onhold->call, e->hangup.cause, -1);
-+                                                  pri_destroy_callonhold(pri, onhold);
-+                                                  onhold = NULL;
-+                                              } else {
-+                                                  ast_log(LOG_NOTICE, "Hangup, did not find cref %d, tei %d\n",e->hangup.cref, e->hangup.tei);
-+                                                  ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 
-+                                                      PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-+                                              }
-                                       }
-                               } 
-                               break;
-@@ -9308,15 +10081,23 @@ static void *pri_dchannel(void *vpri)
-                       case PRI_EVENT_HANGUP_REQ:
-                               chanpos = pri_find_principle(pri, e->hangup.channel);
-                               if (chanpos < 0) {
--                                      ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 
--                                              PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
--                              } else {
-+                                      if (pri->nodetype == BRI_NETWORK_PTMP) {
-+                                          pri_hangup(pri->pri, e->hangup.call, e->hangup.cause, -1);
++                                              /* And take them out of the parking lot */
++                                              if (pl)
++                                                      pl->next = pu->next;
++                                              else
++                                                      aalot = pu->next;
++                                              pt = pu;
++                                              pu = pu->next;
++                                              free(pt);
++                                              break;
 +                                      } else {
-+                                          ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 
-+                                              PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
++                                              /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
++                                              ast_frfree(f);
++                                              goto std;       /* XXX Ick: jumping into an else statement??? XXX */
 +                                      }
-+                              } else if ((pri->pvts[chanpos]->priindication_oob != 2) || (!e->hangup.inband_progress) || (!pri->pvts[chanpos]->outgoing)) {
-+                                                                  /* dont hang up if we want to hear inband call progress */
-                                       chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
-                                       if (chanpos > -1) {
-                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                               if (pri->pvts[chanpos]->realcall) 
-                                                       pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
-                                               else if (pri->pvts[chanpos]->owner) {
-+                                                      char tmpstr[256];
-+                                                      snprintf(tmpstr, sizeof(tmpstr), "%d", e->hangup.cause);
-+                                                      pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "PRI_CAUSE", tmpstr);
-                                                       pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
-                                                       if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
-                                                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-@@ -9343,16 +10124,86 @@ static void *pri_dchannel(void *vpri)
-                                                               if (option_verbose > 2)
-                                                                       ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
-                                                                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
-+                                                      if (e->hangup.aoc_units > -1) {
-+                                                          if (pri->pvts[chanpos]->owner) {
-+                                                              char tmpstr[256];
-+                                                              snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
-+                                                              pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
-+                                                          }
-+                                                          if (option_verbose > 2)
-+                                                              ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
-+                                                                      pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
-+                                                      }
-+                                                      if (pri->nodetype == BRI_NETWORK_PTMP) {
-+                                                          // check for bri transfers, not everybody uses ECT...
-+                                                          if (pri->pvts[chanpos]->owner) {
-+                                                              // find on hold call
-+                                                              struct zt_holded_call *onhold = NULL;
-+                                                              struct ast_channel *transferee = NULL;
-+                                                              int transfer_ok = 0;
-+ 
-+                                                              onhold = pri_get_callonhold(pri, -1, e->hangup.tei);
-+ 
-+                                                              if (onhold) {
-+                                                                  if (pri->pvts[chanpos]->pritransfer == 2) {
-+                                                                      if (((pri->pvts[chanpos]->owner->_state != AST_STATE_RING) && (pri->pvts[chanpos]->owner->_state != AST_STATE_RESERVED)) || ((!ast_strlen_zero(pri->pvts[chanpos]->exten)) && (strncasecmp(pri->pvts[chanpos]->exten, "s", sizeof(pri->pvts[chanpos]->exten))))) {
-+                                                                          transferee = ast_get_holded_call(onhold->uniqueid);
-+ 
-+                                                                          if (transferee) {
-+                                                                              if (pri->pvts[chanpos]->owner->_state == AST_STATE_RINGING) {
-+                                                                                  ast_indicate(transferee, AST_CONTROL_RINGING);
-+                                                                              }
-+ 
-+                                                                              pri->pvts[chanpos]->owner->_softhangup &= ~AST_SOFTHANGUP_DEV;
-+  
-+                                                                              ast_mutex_unlock(&transferee->lock);
-+                                                                              if (ast_channel_masquerade(pri->pvts[chanpos]->owner, transferee)) {
-+                                                                                  ast_log(LOG_WARNING, "unable to masquerade\n");
-+                                                                              } else { 
-+                                                                                  /* beware of zombies!!! */
-+                                                                                  ast_set_flag(transferee, AST_FLAG_ZOMBIE);
-+                                                                                  pri->pvts[chanpos]->owner = NULL;
-+                                                                                  pri->pvts[chanpos]->tei = -1;
-+                                                                                  transfer_ok = 1;
-+                                                                              }
-+                                                                          }
-+                                                                      }       
-+                                                                  } else if (pri->pvts[chanpos]->pritransfer == 0) {
-+                                                                      ast_log(LOG_NOTICE, "killing channel %s \n", onhold->uniqueid);
-+                                                                      ast_retrieve_call_to_death(onhold->uniqueid);
-+                                                                      transfer_ok = 1;
-+                                                                  } else if (pri->pvts[chanpos]->pritransfer == 1) {
-+                                                                      /* we use ECT transfers, so just ignore this */
-+                                                                      transfer_ok = 0;
-+                                                                  }
-+                                                      
-+                                                                  if (transfer_ok) {
-+                                                                      onhold->alreadyhungup = 1;      
-+                                                                      pri_hangup(pri->pri, onhold->call, e->hangup.cause, -1);
-+                                                                      onhold = NULL;
-+                                                                  }
-+                                                                  ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+                                                                  break;
-+                                                              } else {
-+                                                                    pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
-+                                                                        pri->pvts[chanpos]->call = NULL;
-+                                                                        pri->pvts[chanpos]->tei = -1;
-+                                                                }
-+                                                          }
-+                                                      }
-                                               } else {
--                                                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
-+                                                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
-                                                       pri->pvts[chanpos]->call = NULL;
-+                                                      pri->pvts[chanpos]->tei = -1;
-                                               }
-                                               if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
--                                                      if (option_verbose > 2)
-+                                                      if ((pri->nodetype != BRI_CPE_PTMP) && (pri->nodetype != BRI_NETWORK_PTMP)) {
-+                                                          if (option_verbose > 2)
-                                                               ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n", 
-                                                                       PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
--                                                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
--                                                      pri->pvts[chanpos]->resetting = 1;
-+                                                          pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
-+                                                          pri->pvts[chanpos]->resetting = 1;
-+                                                      }
-                                               }
- #ifdef SUPPORT_USERUSER
-@@ -9366,9 +10217,39 @@ static void *pri_dchannel(void *vpri)
-                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                       } else {
--                                              ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-+                                              if (pri->nodetype != BRI_NETWORK_PTMP) {
-+                                                  ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-+                                              } else {
-+                                                  // check holded_calls!!!
-+                                                  struct zt_holded_call *onhold = NULL;
-+ 
-+                                                  onhold = pri_get_callonhold(pri, e->hangup.cref, e->hangup.tei);
-+ 
-+                                                  if (onhold) {
-+                                                          pri_hangup(pri->pri, e->hangup.call, e->hangup.cause, -1);
-+                                                          ast_retrieve_call_to_death(onhold->uniqueid);
-+                                                          pri_destroy_callonhold(pri, onhold);
-+                                                          onhold = NULL;
-+                                                  } else {
-+                                                      ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-+                                                  }
-+                                              }
-                                       }
-                               } 
-+                              if ((chanpos > -1) && (pri->pvts[chanpos]->owner) && (pri->pvts[chanpos]->priindication_oob == 2) && (e->hangup.inband_progress) && (pri->pvts[chanpos]->outgoing)) {
-+                                  ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+                                      if (e->hangup.aoc_units > -1) {
-+                                          char tmpstr[256];
-+                                          snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
-+                                          pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
-+                                          if (option_verbose > 2)
-+                                              ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
-+                                                  pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
++                              }
++                      }
++                      if (x >= AST_MAX_FDS) {
++std:                          for (x=0;x<AST_MAX_FDS;x++) {
++                                      /* Keep this one for next one */
++                                      if (pu->chan->fds[x] > -1) {
++                                              FD_SET(pu->chan->fds[x], &nrfds);
++                                              FD_SET(pu->chan->fds[x], &nefds);
++                                              if (pu->chan->fds[x] > max)
++                                                      max = pu->chan->fds[x];
 +                                      }
-+                                      pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
-+                                      ast_channel_setwhentohangup(pri->pvts[chanpos]->owner, 5);
-+                                  ast_mutex_unlock(&pri->pvts[chanpos]->lock);
 +                              }
-                               break;
-                       case PRI_EVENT_HANGUP_ACK:
-                               chanpos = pri_find_principle(pri, e->hangup.channel);
-@@ -9380,6 +10261,7 @@ static void *pri_dchannel(void *vpri)
-                                       if (chanpos > -1) {
-                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                               pri->pvts[chanpos]->call = NULL;
-+                                              pri->pvts[chanpos]->tei = -1;
-                                               pri->pvts[chanpos]->resetting = 0;
-                                               if (pri->pvts[chanpos]->owner) {
-                                                       if (option_verbose > 2) 
-@@ -9396,7 +10278,9 @@ static void *pri_dchannel(void *vpri)
- #endif
++                              /* Keep track of our longest wait */
++                              if ((tms < ms) || (ms < 0))
++                                      ms = tms;
++                              pl = pu;
++                              pu = pu->next;
++                      }
++              }
++              ast_mutex_unlock(&autoanswer_lock);
++              rfds = nrfds;
++              efds = nefds;
++              tv.tv_sec = ms / 1000;
++              tv.tv_usec = (ms % 1000) * 1000;
++              /* Wait for something to happen */
++              ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
++              pthread_testcancel();
++      }
++      return NULL;    /* Never reached */
++}
++
++static int autoanswer_exec(struct ast_channel *chan, void *data)
++{
++      int res=0;
++      struct ast_channel *peer=NULL;
++      struct aauser *pu, *pl=NULL;
++      struct ast_bridge_config config;
++      char *s, *stringp, *aacontext, *aaexten = NULL;
++      char datastring[80];
++      struct ast_module_user *u;
++
++
++      if (!data) {
++              ast_log(LOG_WARNING, "Autoanswer requires an argument (extension number)\n");
++              return -1;
++      }
++      s = ast_strdupa((void *) data);
++      stringp=s;
++      aacontext = strsep(&stringp, "|");
++      aaexten = strsep(&stringp, "|");
++      if (!aaexten) {
++          aaexten = aacontext;
++          aacontext = NULL;
++      }
++      if (!aaexten) {
++              ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
++              return -1;
++      } else {
++              if (!aacontext) {
++                      aacontext = "default";
++              }
++      }
++
++      u = ast_module_user_add(chan);
++      ast_mutex_lock(&autoanswer_lock);
++      pu = aalot;
++      while(pu) {
++              if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
++                      if (pl)
++                              pl->next = pu->next;
++                      else
++                              aalot = pu->next;
++                      break;
++              }
++              pl = pu;
++              pu = pu->next;
++      }
++      ast_mutex_unlock(&autoanswer_lock);
++      if (pu) {
++              peer = pu->chan;
++              free(pu);
++              pu = NULL;
++      }
++      /* JK02: it helps to answer the channel if not already up */
++      if (chan->_state != AST_STATE_UP) {
++              ast_answer(chan);
++      }
++
++      if (peer) {
++              ast_moh_stop(peer);
++              /* Play a courtesy beep in the callED channel to prefix the bridge connecting */
++              if (!ast_strlen_zero(courtesytone)) {
++                      if (!ast_streamfile(peer, courtesytone, peer->language)) {
++                              if (ast_waitstream(peer, "") < 0) {
++                                      ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
++                                      ast_hangup(peer);
++                                      return -1;
++                              }
++                      }
++              }
++
++              res = ast_channel_make_compatible(chan, peer);
++              if (res < 0) {
++                      ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
++                      ast_hangup(peer);
++                      return -1;
++              }
++              /* This runs sorta backwards, since we give the incoming channel control, as if it
++                 were the person called. */
++              if (option_verbose > 2)
++                      ast_verbose(VERBOSE_PREFIX_3 "Channel %s autoanswered  %s\n", peer->name, chan->name);
++              manager_event(EVENT_FLAG_CALL, "Autoanswer",
++                    "Channel: %s\r\n"
++                    "Uniqueid: %s\r\n"
++                    "Channel2: %s\r\n"
++                    "Uniqueid2: %s\r\n"
++                    "Context: %s\r\n"
++                    "Exten: %s\r\n"
++                ,chan->name, chan->uniqueid, peer->name, peer->uniqueid, aacontext, aaexten);
++
++
++              memset(&config,0,sizeof(struct ast_bridge_config));
++              ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
++              ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
++              config.timelimit = 0;
++              config.play_warning = 0;
++              config.warning_freq = 0;
++              config.warning_sound=NULL;
++              res = ast_bridge_call(chan,peer,&config);
++
++              if (option_verbose > 2)
++                      ast_verbose(VERBOSE_PREFIX_3 "returning from bridge %s\n", peer->name);
++                      /* relogin */
++              snprintf(datastring, sizeof(datastring) - 1, "%s|%s", aacontext, aaexten);
++              ast_autoanswer_login(peer, datastring);
++              return res;
++      } else {
++              if (option_verbose > 2)
++                      ast_verbose(VERBOSE_PREFIX_3 "Nobody logged in for autoanswer %s@%s\n", aaexten, aacontext);
++              res = -1;
++      }
++      ast_module_user_remove(u);
++      return res;
++}
++
  
-                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+                                          }
-                                       }
-+                                  }
-                               }
-                               break;
-                       case PRI_EVENT_CONFIG_ERR:
-@@ -9486,10 +10370,22 @@ static void *pri_dchannel(void *vpri)
-                                       ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                       switch (e->notify.info) {
-                                       case PRI_NOTIFY_REMOTE_HOLD:
-+                                              if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
-+                                                  ast_log(LOG_DEBUG, "Received REMOTE_HOLD notification on NETWORK channel. Starting MoH\n");
-+                                                  ast_moh_start(ast_bridged_channel(pri->pvts[chanpos]->owner), NULL, pri->pvts[chanpos]->mohinterpret);
-+                                              } else {
-+                                                  ast_log(LOG_DEBUG, "Received REMOTE_HOLD notification on CPE channel. Not Starting MoH\n");
-+                                              }
-                                               f.subclass = AST_CONTROL_HOLD;
-                                               zap_queue_frame(pri->pvts[chanpos], &f, pri);
-                                               break;
-                                       case PRI_NOTIFY_REMOTE_RETRIEVAL:
-+                                              if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
-+                                                  ast_log(LOG_DEBUG, "Received REMOTE_RETRIEVAL notification on NETWORK channel. Stopping MoH\n");
-+                                                  ast_moh_stop(ast_bridged_channel(pri->pvts[chanpos]->owner));
-+                                              } else {
-+                                                  ast_log(LOG_DEBUG, "Received REMOTE_RETRIEVAL notification on CPE channel.\n");
-+                                              }
-                                               f.subclass = AST_CONTROL_UNHOLD;
-                                               zap_queue_frame(pri->pvts[chanpos], &f, pri);
-                                               break;
-@@ -9497,6 +10393,77 @@ static void *pri_dchannel(void *vpri)
-                                       ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                               }
-                               break;
-+                      case PRI_EVENT_FACILITY:
-+                                  if (e->facility.operation == 0x06) {
-+                                      struct ast_channel *chan = NULL;
-+                                      struct zt_holded_call *onhold = NULL;
-+                                      if (option_verbose > 2) {
-+                                          ast_verbose(VERBOSE_PREFIX_3 "ECT requested by TEI %d for cref %d\n", e->facility.tei, e->facility.cref);
-+                                      }
-+                                      /* search for cref/tei in held calls */
-+                                      onhold = pri_get_callonhold(pri, e->facility.cref, e->facility.tei);
-+                                      if (onhold) {
-+                                          chan = ast_get_holded_call(onhold->uniqueid);
-+                                          onhold->alreadyhungup = 1;
-+                                          onhold = NULL;
-+                                          if (!chan) {
-+                                              /* hang up */
-+                                              pri_hangup(pri->pri, e->facility.call, 16, -1);
-+                                              break;
-+                                          }
-+                                      } else {
-+                                          /* unknown cref/tei */
-+                                          ast_log(LOG_WARNING, "did not find call on hold for cref %d tei %d\n", e->facility.tei, e->facility.cref);
-+                                          /* hang up */
-+                                          pri_hangup(pri->pri, e->facility.call, 16, -1);
-+                                          break;
-+                                      }
-+ 
-+                                      /* find an active call for the same tei */
-+                                      chanpos = pri_find_tei(pri, e->facility.call, e->facility.tei);
-+                                      if (chanpos < 0) {
-+                                          /* did not find active call, hangup call on hold */
-+                                          if (chan) {
-+                                              ast_hangup(chan);
-+                                              chan = NULL;
-+                                          }
-+                                      } else {
-+                                          ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+                                          /* transfer */
-+                                          if (pri->pvts[chanpos]->owner) {
-+                                              if (option_verbose > 3) {
-+                                                  ast_verbose(VERBOSE_PREFIX_3 "ECT: found %s on channel %d for tei %d\n", pri->pvts[chanpos]->owner->name ,chanpos, e->facility.tei);
-+                                              }
-+                                              /* pass callprogress if the channel is not up yet */
-+                                              if (pri->pvts[chanpos]->owner->_state == AST_STATE_RINGING) {
-+                                                  ast_indicate(chan, AST_CONTROL_RINGING);
-+                                              }
-+                                              /* unlock the channel we removed from hold */
-+                                              ast_mutex_unlock(&chan->lock);
-+                                              if (ast_channel_masquerade(pri->pvts[chanpos]->owner, chan)) {
-+                                                  ast_log(LOG_WARNING, "unable to masquerade\n");
-+                                              } else {
-+                                                  /* beware of zombies !!! */
-+                                                  ast_set_flag(chan, AST_FLAG_ZOMBIE);
-+                                              //    chan->zombie = 1;
-+                                              }
-+                                          }
-+                                          ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+                                      }
-+                                      /* disconnect */
-+                                      pri_hangup(pri->pri, e->facility.call, 16, -1);
-+                                  } else if (e->facility.operation == 0x0D) {
-+                                      ast_log(LOG_NOTICE, "call deflection to %s requested.\n", e->facility.forwardnum);
-+                                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+                                          /* transfer */
-+                                          if (pri->pvts[chanpos]->owner) {
-+                                              snprintf(pri->pvts[chanpos]->owner->call_forward, sizeof(pri->pvts[chanpos]->owner->call_forward), "Local/%s@%s", e->facility.forwardnum, pri->pvts[chanpos]->owner->context);
-+                                          }
-+                                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+                                  } else {
-+                                      ast_log(LOG_WARNING, "Unknown facility operation %#x requested.\n", e->facility.operation);
-+                                  }
-+                              break;
-                       default:
-                               ast_log(LOG_DEBUG, "Event: %d\n", e->e);
-                       }
-@@ -9558,7 +10525,7 @@ static int start_pri(struct zt_pri *pri)
-                       pri->fds[i] = -1;
-                       return -1;
-               }
--              pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
-+              pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype, pri->span);
-               /* Force overlap dial if we're doing GR-303! */
-               if (pri->switchtype == PRI_SWITCH_GR303_TMC)
-                       pri->overlapdial = 1;
-@@ -9626,39 +10593,77 @@ static char *complete_span_5(const char 
+ int ast_pickup_call(struct ast_channel *chan)
+ {
+@@ -2460,6 +2918,7 @@ static int load_config(void) 
  
- static int handle_pri_set_debug_file(int fd, int argc, char **argv)
+ static int reload(void)
  {
--      int myfd;
-+      int myfd, x, d;
-+      int span;
-+ 
-+      if (argc < 6) 
-+              return RESULT_SHOWUSAGE;
++      autoanswer_reregister_extensions();
+       return load_config();
+ }
  
-       if (!strncasecmp(argv[1], "set", 3)) {
--              if (argc < 5) 
-+              if (argc < 7) 
-                       return RESULT_SHOWUSAGE;
+@@ -2483,6 +2942,12 @@ static int load_module(void)
+                       "Park a channel", mandescr_park); 
+       }
  
--              if (ast_strlen_zero(argv[4]))
-+              if (!argv[4] || ast_strlen_zero(argv[4]))
-                       return RESULT_SHOWUSAGE;
++      ast_pthread_create(&autoanswer_thread, NULL, do_autoanswer_thread, NULL);
++      if (!res)
++              res |= ast_register_application(autoanswerlogin, autoanswer_login_exec, synopsis3, descrip3);
++      if (!res)
++              res |= ast_register_application(autoanswer, autoanswer_exec, synopsis4, descrip4);
++
+       res |= ast_devstate_prov_add("Park", metermaidstate);
  
-+              if (!argv[5])
-+                      return RESULT_SHOWUSAGE;
-+ 
-+              if (!argv[6] || ast_strlen_zero(argv[6]))
-+                      return RESULT_SHOWUSAGE;
-+ 
-+              span = atoi(argv[6]);
-+              if ((span < 1) && (span > NUM_SPANS)) {
-+                      return RESULT_SUCCESS;
-+              }
-+              
+       return res;
+@@ -2497,6 +2962,8 @@ static int unload_module(void)
+       ast_manager_unregister("Park");
+       ast_cli_unregister_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
+       ast_unregister_application(parkcall);
++      ast_unregister_application(autoanswer);
++      ast_unregister_application(autoanswerlogin);
+       ast_devstate_prov_del("Park");
+       return ast_unregister_application(parkedcall);
+ }
+--- a/include/asterisk/features.h
++++ b/include/asterisk/features.h
+@@ -72,6 +72,12 @@ int ast_park_call(struct ast_channel *ch
+ */
+ int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *host, int timeout, int *extout);
++extern int ast_hold_call(struct ast_channel *chan, struct ast_channel *host);
++extern int ast_masq_hold_call(struct ast_channel *rchan, struct ast_channel *host);
++extern int ast_retrieve_call(struct ast_channel *chan, char *uniqueid);
++extern int ast_retrieve_call_to_death(char *uniqueid);
++extern struct ast_channel *ast_get_holded_call(char *uniqueid);
 +
-               myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
-               if (myfd < 0) {
-                       ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
-                       return RESULT_SUCCESS;
-               }
--
--              ast_mutex_lock(&pridebugfdlock);
--
--              if (pridebugfd >= 0)
--                      close(pridebugfd);
--
--              pridebugfd = myfd;
--              ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
--              
--              ast_mutex_unlock(&pridebugfdlock);
--
--              ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
-+              for (x=0; x < NUM_SPANS; x++) {
-+                  ast_mutex_lock(&pris[x].lock);
-+                  
-+                  if (pris[x].span == span) {
-+                      if (pris[x].debugfd >= 0)
-+                          close(pris[x].debugfd);
-+                      pris[x].debugfd = myfd;
-+                      for (d=0; d < NUM_DCHANS; d++) {
-+                          if (pris[x].dchans[d])
-+                              pri_set_debug_fd(pris[x].dchans[d], myfd);
-+                      }
-+                  }
-+                  ast_mutex_unlock(&pris[x].lock);
-+              }
-+  
-+              ast_cli(fd, "PRI debug output for span %d will be sent to '%s'\n", span, argv[4]);
-       } else {
-+              if (!argv[5] || ast_strlen_zero(argv[5]))
-+                      return RESULT_SHOWUSAGE;
-               /* Assume it is unset */
--              ast_mutex_lock(&pridebugfdlock);
--              close(pridebugfd);
--              pridebugfd = -1;
--              ast_cli(fd, "PRI debug output to file disabled\n");
--              ast_mutex_unlock(&pridebugfdlock);
-+              span = atoi(argv[5]);
-+              if ((span < 1) && (span > NUM_SPANS)) {
-+                      return RESULT_SUCCESS;
-+              }
-+ 
-+              for (x=0; x < NUM_SPANS; x++) {
-+                  ast_mutex_lock(&pris[x].lock);
-+                  
-+                  if (pris[x].span == span) {
-+                      if (pris[x].debugfd >= 0)
-+                          close(pris[x].debugfd);
-+                      pris[x].debugfd = -1;
-+                      for (d=0; d < NUM_DCHANS; d++) {
-+                          if (pris[x].dchans[d])
-+                              pri_set_debug_fd(pris[x].dchans[d], -1);
-+                      }
-+                  }
-+                  ast_mutex_unlock(&pris[x].lock);
-+              }
-+ 
-+              ast_cli(fd, "PRI debug output to file for span %d disabled\n", span);
-       }
+ /*! \brief Determine system parking extension
+  *  Returns the call parking extension for drivers that provide special
+     call parking help */
+--- a/res/res_features.c
++++ b/res/res_features.c
+@@ -66,6 +66,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revisi
+ #include "asterisk/adsi.h"
+ #include "asterisk/devicestate.h"
+ #include "asterisk/monitor.h"
++#include "asterisk/indications.h"
  
-       return RESULT_SUCCESS;
-@@ -9692,6 +10697,7 @@ static int handle_pri_debug(int fd, int 
+ #define DEFAULT_PARK_TIME 45000
+ #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
+@@ -84,6 +85,7 @@ enum {
+ };
  
+ static char *parkedcall = "ParkedCall";
++static char *holdedcall = "HoldedCall";
  
+ static int parkaddhints = 0;                               /*!< Add parking hints automatically */
+ static int parkingtime = DEFAULT_PARK_TIME;                /*!< No more than 45 seconds parked before you do something with them */
+@@ -168,6 +170,22 @@ struct parkeduser {
+       struct parkeduser *next;
+ };
  
++struct holdeduser {
++      struct ast_channel *chan;
++      struct timeval start;
++      int parkingnum;
++      int cref;
++      int tei;
++      /* Where to go if our parking time expires */
++      char context[AST_MAX_EXTENSION];
++      char exten[AST_MAX_EXTENSION];
++      int priority;
++      int parkingtime;
++      char uniqueid[AST_MAX_UNIQUEID];
++      char uniqueidpeer[AST_MAX_UNIQUEID];
++      struct holdeduser *next;
++};
 +
- static int handle_pri_no_debug(int fd, int argc, char *argv[])
- {
-       int span;
-@@ -9841,10 +10847,6 @@ static int handle_pri_show_debug(int fd,
-               }
+ /* auto answer user */
+ struct aauser {
+       struct ast_channel *chan;
+@@ -187,10 +205,16 @@ static pthread_t autoanswer_thread;
  
-       }
--      ast_mutex_lock(&pridebugfdlock);
--      if (pridebugfd >= 0) 
--              ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
--      ast_mutex_unlock(&pridebugfdlock);
-           
-       if (!count) 
-               ast_cli(fd, "No debug set or no PRI running\n");
-@@ -9871,6 +10873,18 @@ static const char pri_show_spans_help[] 
-       "Usage: pri show spans\n"
-       "       Displays PRI Information\n";
+ static struct parkeduser *parkinglot;
  
-+static char bri_debug_help[] = 
-+      "Usage: bri debug span <span>\n"
-+      "       Enables debugging on a given BRI span\n";
-+      
-+static char bri_no_debug_help[] = 
-+      "Usage: bri no debug span <span>\n"
-+      "       Disables debugging on a given BRI span\n";
++static struct holdeduser *holdlist;
 +
-+static char bri_really_debug_help[] = 
-+      "Usage: bri intensive debug span <span>\n"
-+      "       Enables debugging down to the Q.921 level\n";
+ AST_MUTEX_DEFINE_STATIC(parking_lock);        /*!< protects all static variables above */
++AST_MUTEX_DEFINE_STATIC(holding_lock);
 +
- static struct ast_cli_entry zap_pri_cli[] = {
-       { { "pri", "debug", "span", NULL },
-       handle_pri_debug, "Enables PRI debugging on a span",
-@@ -9895,6 +10909,15 @@ static struct ast_cli_entry zap_pri_cli[
-       { { "pri", "show", "debug", NULL },
-       handle_pri_show_debug, "Displays current PRI debug settings" },
+ static pthread_t parking_thread;
++static pthread_t holding_thread;
++
+ char *ast_parking_ext(void)
+ {
+       return parking_ext;
+@@ -2052,6 +2076,282 @@ static int park_exec(struct ast_channel 
+       return res;
+ }
  
-+      { { "bri", "debug", "span", NULL }, handle_pri_debug,
-+        "Enables BRI debugging on a span", bri_debug_help, complete_span_4 },
++int ast_hold_call(struct ast_channel *chan, struct ast_channel *peer)
++{
++      /* We put the user in the parking list, then wake up the parking thread to be sure it looks
++         after these channels too */
++      struct holdeduser *pu;
++      pu = malloc(sizeof(struct holdeduser));
++      if (pu) {
++              memset(pu, 0, sizeof(pu));
++              ast_mutex_lock(&holding_lock);
++              chan->appl = "Holded Call";
++              chan->data = NULL;
 +
-+      { { "bri", "no", "debug", "span", NULL }, handle_pri_no_debug,
-+        "Disables BRI debugging on a span", bri_no_debug_help, complete_span_5 },
++              pu->chan = chan;
++              strncpy(pu->uniqueid, chan->uniqueid, sizeof(pu->uniqueid));
++              strncpy(pu->uniqueidpeer, peer->uniqueid, sizeof(pu->uniqueidpeer));
++              /* Start music on hold */
++              ast_moh_start(pu->chan, NULL, NULL);
++              gettimeofday(&pu->start, NULL);
++              pu->next = holdlist;
++              holdlist = pu;
++              ast_mutex_unlock(&holding_lock);
++              /* Wake up the (presumably select()ing) thread */
++              pthread_kill(holding_thread, SIGURG);
 +
-+      { { "bri", "intense", "debug", "span", NULL }, handle_pri_really_debug,
-+        "Enables REALLY INTENSE BRI debugging", bri_really_debug_help, complete_span_5 },
++              manager_event(EVENT_FLAG_CALL, "HoldedCall",
++                         "Channel1: %s\r\n"
++                         "Channel2: %s\r\n"
++                          "Uniqueid1: %s\r\n"
++                          "Uniqueid2: %s\r\n"
++                             ,pu->chan->name, peer->name, pu->chan->uniqueid, peer->uniqueid);
 +
-       { { "pri", "set", "debug", "file", NULL },
-       handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
-@@ -9902,8 +10925,76 @@ static struct ast_cli_entry zap_pri_cli[
-       handle_pri_set_debug_file, "Ends PRI debug output to file" },
- };
-+static char *zapCD_tdesc = "Call Deflection";
-+static char *zapCD_app = "zapCD";
-+static char *zapCD_synopsis = "Call Deflection";
++      } else {
++              ast_log(LOG_WARNING, "Out of memory\n");
++              return -1;
++      }
++      return 0;
++}
 +
-+static int app_zapCD(struct ast_channel *chan, void *data)
++int ast_masq_hold_call(struct ast_channel *rchan, struct ast_channel *peer)
 +{
-+ struct zt_pvt *p = chan->tech_pvt;
++      struct ast_channel *chan;
++      struct ast_frame *f;
++      /* Make a new, fake channel that we'll use to masquerade in the real one */
++      chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Onhold/%s",rchan->name);
++      if (chan) {
++              /* Let us keep track of the channel name */
++              ast_string_field_build(chan, name, "Onhold/%s",rchan->name);
++              /* Make formats okay */
++              chan->readformat = rchan->readformat;
++              chan->writeformat = rchan->writeformat;
++              ast_channel_masquerade(chan, rchan);
++              /* Setup the extensions and such */
++              strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
++              strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
++              chan->priority = rchan->priority;
++              /* this might be dirty, but we need to preserve the uniqueid */
++              ast_string_field_build(chan, uniqueid, "%s",rchan->uniqueid);
++              /* Make the masq execute */
++              f = ast_read(chan);
++              if (f)
++                      ast_frfree(f);
++              ast_hold_call(chan, peer);
++              return -1;
++      } else {
++              ast_log(LOG_WARNING, "Unable to create holded channel\n");
++              return -1;
++      }
++      return 0;
++}
 +
-+ if((!p->pri) || (!p->pri->pri)) {
-+      return -1;
-+ }
++int ast_retrieve_call(struct ast_channel *chan, char *uniqueid)
++{
++      int res=-1, dres=-1;
++      struct ast_channel *peer=NULL;
++      struct ast_bridge_config config;
 +
-+ if(!data) {
-+     ast_log(LOG_WARNING, "zapCD wants a number to deflect to\n");
-+      return -1;
-+ }
-+ return pri_deflect(p->pri->pri, p->call, data);
-+}
++      peer = ast_get_holded_call(uniqueid);
 +
-+static char *zapInband_tdesc = "Inband Call Progress (pre-answer)";
-+static char *zapInband_app = "zapInband";
-+static char *zapInband_synopsis = "Inband Call Progress";
++      /* JK02: it helps to answer the channel if not already up */
++      if (chan->_state != AST_STATE_UP) {
++              ast_answer(chan);
++      }
 +
-+static int app_zapInband(struct ast_channel *chan, void *data)
++      if (peer) {
++              ast_mutex_unlock(&peer->lock);
++              ast_moh_stop(peer);
++              res = ast_channel_make_compatible(chan, peer);
++              if (res < 0) {
++                      ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
++                      ast_hangup(peer);
++                      return -1;
++              }
++              /* This runs sorta backwards, since we give the incoming channel control, as if it
++                 were the person called. */
++              if (option_verbose > 2)
++                      ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to holded call %s\n", chan->name, peer->name);
++
++              memset(&config,0,sizeof(struct ast_bridge_config));
++              ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
++              ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
++              config.timelimit = 0;
++              config.play_warning = 0;
++              config.warning_freq = 0;
++              config.warning_sound=NULL;
++              res = ast_bridge_call(chan,peer,&config);
++
++              /* Simulate the PBX hanging up */
++              if (res != AST_PBX_NO_HANGUP_PEER)
++                      ast_hangup(peer);
++              return res;
++      } else {
++              /* XXX Play a message XXX */
++        dres = ast_streamfile(chan, "pbx-invalidpark", chan->language);
++        if (!dres)
++          dres = ast_waitstream(chan, "");
++        else {
++          ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
++          dres = 0;
++        }
++      }
++      return res;
++}
++
++int ast_retrieve_call_to_death(char *uniqueid)
 +{
-+ struct zt_pvt *p = chan->tech_pvt;
++      int res=-1;
++      struct ast_channel *peer=NULL;
 +
-+ return pri_acknowledge(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1);
++      peer = ast_get_holded_call(uniqueid);
++
++      if (peer) {
++              res=0;
++              if (option_verbose > 2)
++                      ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
++              ast_mutex_unlock(&peer->lock);
++              ast_hangup(peer);
++      } else {
++              ast_log(LOG_WARNING, "Could not find channel with uniqueid %s to retrieve.\n", uniqueid);
++      }
++      return res;
 +}
 +
- #endif /* HAVE_PRI */
-+static int app_zapEC(struct ast_channel *chan, void *data)
++struct ast_channel *ast_get_holded_call(char *uniqueid)
 +{
-+ int res=-1;
-+ struct zt_pvt *p = NULL;
++      int res=-1;
++      struct ast_channel *peer=NULL;
++      struct holdeduser *pu, *pl=NULL;
 +
-+ if (!data) {
-+      ast_log(LOG_WARNING, "zapEC requires one argument (on | off)\n");
-+ }
-+ if (chan && !strcasecmp("ZAP",chan->tech->type)) {
-+      p = chan->tech_pvt;
-+      if (!p) return res;
-+      if (!strcasecmp("on",(char *)data)) {
-+          zt_enable_ec(p);
-+          res = 0;
-+          if (option_verbose > 3) {
-+              ast_verbose(VERBOSE_PREFIX_3 "Enabled echo cancelation on channel %s.\n", chan->name);
-+          }
-+      } else if (!strcasecmp("off",(char *)data)) {
-+          zt_disable_ec(p);
-+          res = 0;
-+          if (option_verbose > 3) {
-+              ast_verbose(VERBOSE_PREFIX_3 "Disabled echo cancelation on channel %s.\n", chan->name);
-+          }
++      ast_mutex_lock(&holding_lock);
++      pu = holdlist;
++      while(pu) {
++              if (!strncmp(uniqueid,pu->uniqueid,sizeof(pu->uniqueid))) {
++                      if (pl)
++                              pl->next = pu->next;
++                      else
++                              holdlist = pu->next;
++                      break;
++              }
++              pl = pu;
++              pu = pu->next;
++      }
++      ast_mutex_unlock(&holding_lock);
++      if (pu) {
++              peer = ast_get_channel_by_uniqueid_locked(pu->uniqueid);
++              free(pu);
++              if (peer) {
++                  res=0;
++                  if (option_verbose > 2)
++                      ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
++                  ast_moh_stop(peer);
++                  return peer;
++              } else {
++                  if (option_verbose > 2)
++                      ast_verbose(VERBOSE_PREFIX_3 "Could not find channel with uniqueid %s.\n", uniqueid);
++                  return NULL;
++              }
 +      } else {
-+          ast_log(LOG_WARNING, "Unknown argument %s to zapEC\n", (char *)data);
++              ast_log(LOG_WARNING, "Could not find held channel with uniqueid %s to retrieve.\n", uniqueid);
++      }
++      return NULL;
++}
++
++/* this is our autmagically service thread that keeps channels onhold happy */
++static void *do_holding_thread(void *ignore)
++{
++      int ms, tms, max;
++      struct holdeduser *pu, *pl, *pt = NULL;
++      struct timeval tv;
++      struct ast_frame *f;
++      int x;
++      fd_set rfds, efds;
++      fd_set nrfds, nefds;
++      FD_ZERO(&rfds);
++      FD_ZERO(&efds);
++      for (;;) {
++              ms = -1;
++              max = -1;
++              ast_mutex_lock(&holding_lock);
++              pl = NULL;
++              pu = holdlist;
++              gettimeofday(&tv, NULL);
++              FD_ZERO(&nrfds);
++              FD_ZERO(&nefds);
++              while(pu) {
++                      tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
++                              for (x=0;x<AST_MAX_FDS;x++) {
++                                      if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
++                                              if (FD_ISSET(pu->chan->fds[x], &efds))
++                                                      ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
++                                              else
++                                                      ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
++                                              pu->chan->fdno = x;
++                                              /* See if they need servicing */
++                                              f = ast_read(pu->chan);
++                                              if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass ==  AST_CONTROL_HANGUP))) {
++                                                      /* There's a problem, hang them up*/
++                                                      if (option_verbose > 1)
++                                                              ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being onhold\n", pu->chan->name);
++                                                      ast_hangup(pu->chan);
++                                                      /* find the corresponding channel and hang them up too! */
++                                                      /* but only if it is not bridged yet! */
++                                                      /* And take them out of the parking lot */
++                                                      if (pl)
++                                                              pl->next = pu->next;
++                                                      else
++                                                              holdlist = pu->next;
++                                                      pt = pu;
++                                                      pu = pu->next;
++                                                      free(pt);
++                                                      break;
++                                              } else {
++                                                      /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
++                                                      ast_frfree(f);
++                                                      goto std;       /* XXX Ick: jumping into an else statement??? XXX */
++                                              }
++                                      }
++                              }
++                              if (x >= AST_MAX_FDS) {
++std:                                  for (x=0;x<AST_MAX_FDS;x++) {
++                                              /* Keep this one for next one */
++                                              if (pu->chan->fds[x] > -1) {
++                                                      FD_SET(pu->chan->fds[x], &nrfds);
++                                                      FD_SET(pu->chan->fds[x], &nefds);
++                                                      if (pu->chan->fds[x] > max)
++                                                              max = pu->chan->fds[x];
++                                              }
++                                      }
++                                      /* Keep track of our longest wait */
++                                      if ((tms < ms) || (ms < 0))
++                                              ms = tms;
++                                      pl = pu;
++                                      pu = pu->next;
++                              }
++              }
++              ast_mutex_unlock(&holding_lock);
++              rfds = nrfds;
++              efds = nefds;
++              tv.tv_sec = ms / 1000;
++              tv.tv_usec = (ms % 1000) * 1000;
++              /* Wait for something to happen */
++              ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
++              pthread_testcancel();
 +      }
-+ } else {
-+  ast_log(LOG_WARNING, "zapNoEC only works on ZAP channels, check your extensions.conf!\n");
-+  res = 0;
-+ }
-+
-+ return res;
++      return NULL;    /* Never reached */
 +}
 +
-+static char *zapEC_tdesc = "Enable/disable Echo cancelation";
-+static char *zapEC_app = "zapEC";
-+static char *zapEC_synopsis = "Enable/Disable Echo Cancelation on a Zap channel";
++static int retrieve_call_exec(struct ast_channel *chan, void *data) {
++      int res=0;
++      struct ast_module_user *u;
++      char *uniqueid = (char *)data;
++      u = ast_module_user_add(chan);
++          res = ast_retrieve_call(chan, uniqueid);
++      ast_module_user_remove(u);
++      return res;
++}
 +
- static int zap_destroy_channel(int fd, int argc, char **argv)
+ static int handle_showfeatures(int fd, int argc, char *argv[])
  {
-       int channel;
-@@ -10484,8 +11575,11 @@ static int __unload_module(void)
+       int i;
+@@ -2933,6 +3233,7 @@ static int load_module(void)
+               return res;
+       ast_cli_register_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
+       ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
++      ast_pthread_create(&holding_thread, NULL, do_holding_thread, NULL);
+       res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
+       if (!res)
+               res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
+@@ -2942,6 +3243,7 @@ static int load_module(void)
+                       "Park a channel", mandescr_park); 
        }
-       ast_cli_unregister_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(struct ast_cli_entry));
-       ast_unregister_application(zap_send_keypad_facility_app);
-+      ast_unregister_application(zapCD_app);
-+      ast_unregister_application(zapInband_app);
- #endif
-       ast_cli_unregister_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
-+      ast_unregister_application(zapEC_app);
-       ast_manager_unregister( "ZapDialOffhook" );
-       ast_manager_unregister( "ZapHangup" );
-       ast_manager_unregister( "ZapTransfer" );
-@@ -10987,6 +12081,22 @@ static int process_zap(struct zt_chan_co
-                                       confp->chan.sig = SIG_GR303FXSKS;
-                                       confp->chan.radio = 0;
-                                       confp->pri.nodetype = PRI_CPE;
-+                              } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
-+                                      confp->chan.radio = 0;
-+                                      confp->chan.sig = SIG_PRI;
-+                                      confp->pri.nodetype = BRI_NETWORK_PTMP;
-+                              } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
-+                                      confp->chan.sig = SIG_PRI;
-+                                      confp->chan.radio = 0;
-+                                      confp->pri.nodetype = BRI_CPE_PTMP;
-+                              } else if (!strcasecmp(v->value, "bri_net")) {
-+                                      confp->chan.radio = 0;
-+                                      confp->chan.sig = SIG_PRI;
-+                                      confp->pri.nodetype = BRI_NETWORK;
-+                              } else if (!strcasecmp(v->value, "bri_cpe")) {
-+                                      confp->chan.sig = SIG_PRI;
-+                                      confp->chan.radio = 0;
-+                                      confp->pri.nodetype = BRI_CPE;
- #endif
-                               } else {
-                                       ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
-@@ -11099,9 +12209,21 @@ static int process_zap(struct zt_chan_co
-                                       confp->chan.priindication_oob = 1;
-                               else if (!strcasecmp(v->value, "inband"))
-                                       confp->chan.priindication_oob = 0;
-+                              else if (!strcasecmp(v->value, "passthrough"))
-+                                      confp->chan.priindication_oob = 2;
-                               else
--                                      ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
-+                                      ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband', 'outofband' or 'passthrough' at line %d\n",
-                                               v->value, v->lineno);
-+                      } else if (!strcasecmp(v->name, "pritransfer")) {
-+                              if (!strcasecmp(v->value, "no"))
-+                                      confp->chan.pritransfer = 0;
-+                              else if (!strcasecmp(v->value, "ect"))
-+                                      confp->chan.pritransfer = 1;
-+                              else if (!strcasecmp(v->value, "hangup"))
-+                                      confp->chan.pritransfer = 2;
-+                              else
-+                                      ast_log(LOG_WARNING, "'%s' is not a valid pri transfer value, should be 'no' , 'ect' or 'hangup' at line %d\n",
-+                                              v->value, v->lineno);
-                       } else if (!strcasecmp(v->name, "priexclusive")) {
-                               confp->chan.priexclusive = ast_true(v->value);
-                       } else if (!strcasecmp(v->name, "internationalprefix")) {
-@@ -11114,6 +12236,10 @@ static int process_zap(struct zt_chan_co
-                               ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
-                       } else if (!strcasecmp(v->name, "unknownprefix")) {
-                               ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
-+                      } else if (!strcasecmp(v->name, "nocid")) {
-+                              ast_copy_string(confp->pri.nocid, v->value, sizeof(confp->pri.nocid));
-+                      } else if (!strcasecmp(v->name, "withheldcid")) {
-+                              ast_copy_string(confp->pri.withheldcid, v->value, sizeof(confp->pri.withheldcid));
-                       } else if (!strcasecmp(v->name, "resetinterval")) {
-                               if (!strcasecmp(v->value, "never"))
-                                       confp->pri.resetinterval = -1;
-@@ -11130,6 +12256,8 @@ static int process_zap(struct zt_chan_co
-                               ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
-                       } else if (!strcasecmp(v->name, "idledial")) {
-                               ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
-+                      } else if (!strcasecmp(v->name, "pritrustusercid")) {
-+                              confp->pri.usercid = ast_true(v->value);
-                       } else if (!strcasecmp(v->name, "overlapdial")) {
-                               confp->pri.overlapdial = ast_true(v->value);
-                       } else if (!strcasecmp(v->name, "pritimer")) {
-@@ -11431,6 +12559,7 @@ static int setup_zap(int reload)
- #ifdef HAVE_PRI
-       if (!reload) {
-               for (x = 0; x < NUM_SPANS; x++) {
-+                      pris[x].debugfd = -1;
-                       if (pris[x].pvts[0]) {
-                               if (start_pri(pris + x)) {
-                                       ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
-@@ -11478,7 +12607,10 @@ static int load_module(void)
-       ast_string_field_init(&inuse, 16);
-       ast_string_field_set(&inuse, name, "GR-303InUse");
-       ast_cli_register_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(struct ast_cli_entry));
-+      ast_register_application(zapCD_app, app_zapCD, zapCD_synopsis, zapCD_tdesc);
-+        ast_register_application(zapInband_app, app_zapInband, zapInband_synopsis, zapInband_tdesc);
- #endif        
-+      ast_register_application(zapEC_app, app_zapEC, zapEC_synopsis, zapEC_tdesc);
-       ast_cli_register_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
-       
-       memset(round_robin, 0, sizeof(round_robin));
-@@ -11512,6 +12644,7 @@ static int zt_sendtext(struct ast_channe
-       float scont = 0.0;
-       int index;
  
-+
-       index = zt_get_index(c, p, 0);
-       if (index < 0) {
-               ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
---- a/configs/zapata.conf.sample
-+++ b/configs/zapata.conf.sample
-@@ -123,9 +123,20 @@ switchtype=national
- ; 
- ; outofband:      Signal Busy/Congestion out of band with RELEASE/DISCONNECT
- ; inband:         Signal Busy/Congestion using in-band tones
-+; passthrough:          Listen to the telco
- ;
- ; priindication = outofband
- ;
-+; PRI/BRI transfers (HOLD -> SETUP -> ECT/Hangup)
-+;
-+; Configure how transfers are initiated. ECT should be preferred
-+;
-+; no:         no transfers allowed (results in hangup)
-+; ect:        use ECT (facility)
-+; hangup:     transfer on hangup (if your phones dont support ECT)
-+;
-+; pritransfer = ect
-+;
- ; If you need to override the existing channels selection routine and force all
- ; PRI channels to be marked as exclusively selected, set this to yes.
- ; priexclusive = yes
---- a/main/channel.c
-+++ b/main/channel.c
-@@ -4209,6 +4209,10 @@ enum ast_bridge_result ast_channel_bridg
-                       c1->name, c1->_bridge->name);
-               return -1;
-       }
-+
-+      if (IS_DIGITAL(c0->transfercapability) || IS_DIGITAL(c1->transfercapability)) {
-+          config->flags = 0;
-+      }
-       
-       /* Stop if we're a zombie or need a soft hangup */
-       if (ast_test_flag(c0, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c0) ||
++      res |= ast_register_application(holdedcall, retrieve_call_exec, synopsis, descrip);
+       ast_pthread_create(&autoanswer_thread, NULL, do_autoanswer_thread, NULL);
+       if (!res)
+               res |= ast_register_application(autoanswerlogin, autoanswer_login_exec, synopsis3, descrip3);
+@@ -2964,6 +3266,7 @@ static int unload_module(void)
+       ast_unregister_application(parkcall);
+       ast_unregister_application(autoanswer);
+       ast_unregister_application(autoanswerlogin);
++      ast_unregister_application(holdedcall);
+       ast_devstate_prov_del("Park");
+       return ast_unregister_application(parkedcall);
+ }
 --- a/channels/chan_zap.c
 +++ b/channels/chan_zap.c
 @@ -77,6 +77,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revisi
  #ifdef HAVE_PRI
- #include <libpri.h>
+ #include <bristuffed/libpri.h>
  #endif
 +#ifdef HAVE_GSMAT
 +#include <libgsmat.h>
@@ -7779,7 +6951,7 @@ Add or convert channel operations so they can use the unique ID.
  
  #include "asterisk/lock.h"
  #include "asterisk/channel.h"
-@@ -187,6 +190,7 @@ static const char config[] = "zapata.con
+@@ -185,6 +188,7 @@ static const char config[] = "zapata.con
  #define SIG_FXOGS     ZT_SIG_FXOGS
  #define SIG_FXOKS     ZT_SIG_FXOKS
  #define SIG_PRI               ZT_SIG_CLEAR
@@ -7787,7 +6959,7 @@ Add or convert channel operations so they can use the unique ID.
  #define       SIG_SF          ZT_SIG_SF
  #define SIG_SFWINK    (0x0100000 | ZT_SIG_SF)
  #define SIG_SF_FEATD  (0x0200000 | ZT_SIG_SF)
-@@ -236,6 +240,8 @@ static int matchdigittimeout = 3000;
+@@ -234,6 +238,8 @@ static int matchdigittimeout = 3000;
  /*! \brief Protect the interface list (of zt_pvt's) */
  AST_MUTEX_DEFINE_STATIC(iflock);
  
@@ -7796,16 +6968,15 @@ Add or convert channel operations so they can use the unique ID.
  
  static int ifcount = 0;
  
-@@ -251,7 +257,7 @@ static int restart_monitor(void);
- static enum ast_bridge_result zt_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
+@@ -251,6 +257,7 @@ static enum ast_bridge_result zt_bridge(
  
--static int zt_sendtext(struct ast_channel *c, const char *text);
-+static int zt_sendtext(struct ast_channel *c, const char *dest, const char *text, int ispdu);
+ static int zt_sendtext(struct ast_channel *c, const char *text);
  
++static int zt_sendmessage(struct ast_channel *c, const char *dest, const char *text, int ispdu);
  
  /*! \brief Avoid the silly zt_getevent which ignores a bunch of events */
-@@ -366,6 +372,19 @@ struct zt_pri {
+ static inline int zt_get_event(int fd)
+@@ -364,6 +371,19 @@ struct zt_pri {
        int debugfd;
  };
  
@@ -7825,7 +6996,7 @@ Add or convert channel operations so they can use the unique ID.
  
  static struct zt_pri pris[NUM_SPANS];
  
-@@ -394,6 +413,7 @@ struct zt_pri;
+@@ -392,6 +412,7 @@ struct zt_pri;
  #define POLARITY_REV    1
  
  
@@ -7833,7 +7004,7 @@ Add or convert channel operations so they can use the unique ID.
  static struct zt_distRings drings;
  
  struct distRingData {
-@@ -605,6 +625,9 @@ static struct zt_pvt {
+@@ -604,6 +625,9 @@ static struct zt_pvt {
        int prioffset;
        int logicalspan;
  #endif        
@@ -7843,16 +7014,26 @@ Add or convert channel operations so they can use the unique ID.
        int polarity;
        int dsp_features;
        char begindigit;
-@@ -711,7 +734,7 @@ static struct zt_chan_conf zt_chan_conf_
+@@ -710,7 +734,7 @@ static struct zt_chan_conf zt_chan_conf_
  static struct ast_channel *zt_request(const char *type, int format, void *data, int *cause);
  static int zt_digit_begin(struct ast_channel *ast, char digit);
  static int zt_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
 -static int zt_sendtext(struct ast_channel *c, const char *text);
-+static int zt_sendtext(struct ast_channel *c, const char *dest, const char *text, int ispdu);
++static int zt_sendmessage(struct ast_channel *c, const char *dest, const char *text, int ispdu);
  static int zt_call(struct ast_channel *ast, char *rdest, int timeout);
  static int zt_hangup(struct ast_channel *ast);
  static int zt_answer(struct ast_channel *ast);
-@@ -1370,6 +1393,8 @@ static char *zap_sig2str(int sig)
+@@ -732,6 +756,9 @@ static const struct ast_channel_tech zap
+       .send_digit_begin = zt_digit_begin,
+       .send_digit_end = zt_digit_end,
+       .send_text = zt_sendtext,
++#if 0 /* we (Debian) disable that addition because of ABI breakage */
++      .send_message = zt_sendmessage,
++#endif
+       .call = zt_call,
+       .hangup = zt_hangup,
+       .answer = zt_answer,
+@@ -1262,6 +1289,8 @@ static char *zap_sig2str(int sig)
                return "GR-303 with FXOKS";
        case SIG_GR303FXSKS:
                return "GR-303 with FXSKS";
@@ -7861,7 +7042,7 @@ Add or convert channel operations so they can use the unique ID.
        case 0:
                return "Pseudo";
        default:
-@@ -1791,7 +1816,7 @@ static inline int zt_confmute(struct zt_
+@@ -1683,7 +1712,7 @@ static inline int zt_confmute(struct zt_
  {
        int x, y, res;
        x = muted;
@@ -7870,7 +7051,7 @@ Add or convert channel operations so they can use the unique ID.
                y = 1;
                res = ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &y);
                if (res)
-@@ -2206,6 +2231,25 @@ static int zt_call(struct ast_channel *a
+@@ -2098,6 +2127,25 @@ static int zt_call(struct ast_channel *a
                p->dialdest[0] = '\0';
                disable_dtmf_detect(p);
                break;
@@ -7896,7 +7077,7 @@ Add or convert channel operations so they can use the unique ID.
        default:
                ast_log(LOG_DEBUG, "not yet implemented\n");
                ast_mutex_unlock(&p->lock);
-@@ -2845,7 +2889,13 @@ static int zt_hangup(struct ast_channel 
+@@ -2737,7 +2785,13 @@ static int zt_hangup(struct ast_channel 
                        }
                }
  #endif
@@ -7911,7 +7092,7 @@ Add or convert channel operations so they can use the unique ID.
                        res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_ONHOOK);
                if (res < 0) {
                        ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
-@@ -3022,6 +3072,13 @@ static int zt_answer(struct ast_channel 
+@@ -2914,6 +2968,13 @@ static int zt_answer(struct ast_channel 
                zt_train_ec(p);
                break;
  #endif
@@ -7925,7 +7106,7 @@ Add or convert channel operations so they can use the unique ID.
        case 0:
                ast_mutex_unlock(&p->lock);
                return 0;
-@@ -7384,6 +7441,10 @@ static int pri_create_spanmap(int span, 
+@@ -7302,6 +7363,10 @@ static int pri_create_spanmap(int span, 
  
  #endif
  
@@ -7933,15 +7114,15 @@ Add or convert channel operations so they can use the unique ID.
 +static void *gsm_dchannel(void *vgsm);
 +#endif
 +
- static struct zt_pvt *mkintf(int channel, struct zt_chan_conf conf, struct zt_pri *pri, int reloading)
+ static struct zt_pvt *mkintf(int channel, const struct zt_chan_conf *conf, struct zt_pri *pri, int reloading)
  {
        /* Make a zt_pvt structure for this interface (or CRV if "pri" is specified) */
-@@ -7612,6 +7673,37 @@ static struct zt_pvt *mkintf(int channel
+@@ -7530,6 +7595,37 @@ static struct zt_pvt *mkintf(int channel
                                tmp->prioffset = 0;
                        }
  #endif
 +#ifdef HAVE_GSMAT
-+              if (conf.chan.sig == SIG_GSM) {
++              if (conf->chan.sig == SIG_GSM) {
 +                  struct zt_bufferinfo bi;
 +                  ast_mutex_init(&tmp->gsm.lock);
 +                  strncpy(tmp->gsm.pin, gsm_modem_pin, sizeof(tmp->gsm.pin) - 1);
@@ -7972,9 +7153,9 @@ Add or convert channel operations so they can use the unique ID.
 +              }
 +#endif
                } else {
-                       conf.chan.sig = tmp->sig;
-                       conf.chan.radio = tmp->radio;
-@@ -7895,6 +7987,12 @@ static inline int available(struct zt_pv
+                       conf->chan.sig = tmp->sig;
+                       conf->chan.radio = tmp->radio;
+@@ -7819,6 +7915,12 @@ static inline int available(struct zt_pv
                                return 1;
                }
  #endif
@@ -7987,7 +7168,7 @@ Add or convert channel operations so they can use the unique ID.
                if (!(p->radio || (p->oprmode < 0)))
                {
                        if (!p->sig || (p->sig == SIG_FXSLS))
-@@ -8249,6 +8347,235 @@ next:
+@@ -8176,6 +8278,235 @@ next:
        return tmp;
  }
  
@@ -8125,7 +7306,7 @@ Add or convert channel operations so they can use the unique ID.
 +                      "Length: %d\r\n"
 +                      "Text: %s\r\n"
 +                      "PDU: %s\r\n",
-+                      gsm->span, 
++                      gsm->span,
 +                      e->sm_received.sender,
 +                      e->sm_received.smsc,
 +                      e->sm_received.len,
@@ -8153,7 +7334,7 @@ Add or convert channel operations so they can use the unique ID.
 +      }
 +      gsm_set_debug(gsm->modul, GSM_DEBUG_NONE);
 +      for (;;) {
-+              
++
 +              /* Run the D-Channel */
 +              FD_ZERO(&rfds);
 +              FD_ZERO(&efds);
@@ -8184,7 +7365,7 @@ Add or convert channel operations so they can use the unique ID.
 +              } else if (errno == ELAST) {
 +                      res = ioctl(gsm->fd, ZT_GETEVENT, &x);
 +                      printf("Got Zaptel event: %d\n", x);
-+              } else if (errno != EINTR) 
++              } else if (errno != EINTR)
 +                      fprintf(stderr, "Error (%d) on select: %s\n", ELAST, strerror(errno));
 +
 +              if (!e) {
@@ -8223,7 +7404,7 @@ Add or convert channel operations so they can use the unique ID.
  #ifdef HAVE_PRI
  static struct zt_pvt *pri_find_crv(struct zt_pri *pri, int crv)
  {
-@@ -8524,6 +8851,18 @@ static void zt_pri_error(char *s, int sp
+@@ -8450,6 +8781,18 @@ static void zt_pri_error(char *s, int sp
        ast_log(LOG_WARNING, "%d %s", span, s);
  }
  
@@ -8242,7 +7423,7 @@ Add or convert channel operations so they can use the unique ID.
  static int pri_check_restart(struct zt_pri *pri)
  {
        if ((pri->nodetype != PRI_NETWORK) && (pri->nodetype != PRI_CPE)) {
-@@ -10957,6 +11296,243 @@ static int app_zapInband(struct ast_chan
+@@ -10868,6 +11211,243 @@ static int app_zapInband(struct ast_chan
  
  #endif /* HAVE_PRI */
  
@@ -8283,7 +7464,7 @@ Add or convert channel operations so they can use the unique ID.
 +          }
 +          pvt = pvt->next;
 +      }
-+      
++
 +      ast_cli(fd, "No GSM running on channel %d\n", channel);
 +      return RESULT_SUCCESS;
 +}
@@ -8312,15 +7493,15 @@ Add or convert channel operations so they can use the unique ID.
 + return handle_gsm_debug_helper(fd, channel, GSM_DEBUG_NONE);
 +}
 +
-+static char zap_reset_help[] = 
++static char zap_reset_help[] =
 +      "Usage: zap reset span <span>\n"
 +      "       Reset/Restart a zaptel span\n";
 +
-+static char gsm_debug_help[] = 
++static char gsm_debug_help[] =
 +      "Usage: gsm debug channel <channel>\n"
 +      "       Enables debugging on a given GSM channel\n";
-+      
-+static char gsm_no_debug_help[] = 
++
++static char gsm_no_debug_help[] =
 +      "Usage: gsm no debug channel <channel>\n"
 +      "       Disables debugging on a given GSM channel\n";
 +
@@ -8335,7 +7516,7 @@ Add or convert channel operations so they can use the unique ID.
 +
 +
 +
-+static char gsm_send_pdu_help[] = 
++static char gsm_send_pdu_help[] =
 +      "Usage: gsm send pdu <channel> <pdu>\n"
 +      "       Sends a PDU on a GSM channel\n";
 +
@@ -8369,7 +7550,7 @@ Add or convert channel operations so they can use the unique ID.
 +          }
 +          pvt = pvt->next;
 +      }
-+      
++
 +      return RESULT_SUCCESS;
 +}
 +
@@ -8377,7 +7558,7 @@ Add or convert channel operations so they can use the unique ID.
 +      { "gsm", "send", "pdu", NULL }, handle_gsm_send_pdu, "Sends a SM on a GSM channel", gsm_send_pdu_help, complete_span_4 };
 +
 +
-+static char gsm_send_sms_help[] = 
++static char gsm_send_sms_help[] =
 +      "Usage: gsm send sms <channel> <destination> <message>\n"
 +      "       Sends a SM on a GSM channel\n";
 +
@@ -8410,7 +7591,7 @@ Add or convert channel operations so they can use the unique ID.
 +          }
 +          pvt = pvt->next;
 +      }
-+      
++
 +      return RESULT_SUCCESS;
 +}
 +
@@ -8418,16 +7599,16 @@ Add or convert channel operations so they can use the unique ID.
 +     struct zt_pvt *pvt = NULL;
 +     char *c = NULL;
 +     pvt = chan->tech_pvt;
-+     
++
 +     if (!pvt) return -1;
-+     
++
 +     /* parse dialstring */
 +     c = strrchr(dest, '/');
 +     if (c)
 +      c++;
 +     else
 +      c = (char *)dest;
-+ 
++
 +     ast_mutex_lock(&pvt->lock);
 +      if (ispdu) {
 +          gsm_sms_send_pdu(pvt->gsm.modul, (char *)text);
@@ -8438,11 +7619,11 @@ Add or convert channel operations so they can use the unique ID.
 +     gsm_wait(pvt->gsm.modul);
 +     return 0;
 +}
-+ 
++
 +static struct ast_cli_entry gsm_send_sms = {
 +      { "gsm", "send", "sms", NULL }, handle_gsm_send_sms, "Sends a SM on a GSM channel", gsm_send_sms_help, complete_span_4 };
 +
-+static char gsm_show_status_help[] = 
++static char gsm_show_status_help[] =
 +      "Usage: gsm show status <channel>>\n"
 +      "       Displays status information about the GSM channel.\n";
 +
@@ -8474,7 +7655,7 @@ Add or convert channel operations so they can use the unique ID.
 +          }
 +          pvt = pvt->next;
 +      }
-+      
++
 +      return RESULT_SUCCESS;
 +}
 +
@@ -8486,7 +7667,7 @@ Add or convert channel operations so they can use the unique ID.
  static int app_zapEC(struct ast_channel *chan, void *data)
  {
   int res=-1;
-@@ -11578,6 +12154,12 @@ static int __unload_module(void)
+@@ -11489,6 +12069,12 @@ static int __unload_module(void)
        ast_unregister_application(zapCD_app);
        ast_unregister_application(zapInband_app);
  #endif
@@ -8499,7 +7680,7 @@ Add or convert channel operations so they can use the unique ID.
        ast_cli_unregister_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
        ast_unregister_application(zapEC_app);
        ast_manager_unregister( "ZapDialOffhook" );
-@@ -12098,6 +12680,11 @@ static int process_zap(struct zt_chan_co
+@@ -12009,6 +12595,11 @@ static int process_zap(struct zt_chan_co
                                        confp->chan.radio = 0;
                                        confp->pri.nodetype = BRI_CPE;
  #endif
@@ -8507,11 +7688,11 @@ Add or convert channel operations so they can use the unique ID.
 +                              } else if (!strcasecmp(v->value, "gsm")) {
 +                                      confp->chan.sig = SIG_GSM;
 +                                      confp->chan.radio = 0;
-+#endif                                
++#endif
                                } else {
                                        ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
                                }
-@@ -12240,6 +12827,10 @@ static int process_zap(struct zt_chan_co
+@@ -12151,6 +12742,10 @@ static int process_zap(struct zt_chan_co
                                ast_copy_string(confp->pri.nocid, v->value, sizeof(confp->pri.nocid));
                        } else if (!strcasecmp(v->name, "withheldcid")) {
                                ast_copy_string(confp->pri.withheldcid, v->value, sizeof(confp->pri.withheldcid));
@@ -8522,7 +7703,7 @@ Add or convert channel operations so they can use the unique ID.
                        } else if (!strcasecmp(v->name, "resetinterval")) {
                                if (!strcasecmp(v->value, "never"))
                                        confp->pri.resetinterval = -1;
-@@ -12594,6 +13185,10 @@ static int load_module(void)
+@@ -12506,6 +13101,10 @@ static int load_module(void)
        ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
                        zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
  #endif
@@ -8533,7 +7714,7 @@ Add or convert channel operations so they can use the unique ID.
        res = setup_zap(0);
        /* Make sure we can register our Zap channel type */
        if (res)
-@@ -12612,6 +13207,12 @@ static int load_module(void)
+@@ -12524,6 +13123,12 @@ static int load_module(void)
  #endif        
        ast_register_application(zapEC_app, app_zapEC, zapEC_synopsis, zapEC_tdesc);
        ast_cli_register_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
@@ -8546,7 +7727,7 @@ Add or convert channel operations so they can use the unique ID.
        
        memset(round_robin, 0, sizeof(round_robin));
        ast_manager_register( "ZapTransfer", 0, action_transfer, "Transfer Zap Channel" );
-@@ -12625,7 +13226,48 @@ static int load_module(void)
+@@ -12537,7 +13142,66 @@ static int load_module(void)
        return res;
  }
  
@@ -8559,7 +7740,7 @@ Add or convert channel operations so they can use the unique ID.
 + if (!p) return -1;
 + if (!p->pri) return -1;
 +          if (strlen(text)) {
-+              if (p->pri) {           
++              if (p->pri) {
 +                  if (!pri_grab(p, p->pri)) {
 +              //      ast_log(LOG_NOTICE, "Sending Display IE  '%s'\n", text);
 +                      pri_information_display(p->pri->pri,p->call,(char *)text);
@@ -8571,11 +7752,25 @@ Add or convert channel operations so they can use the unique ID.
 +}
 +#endif
 +
-+static int zt_sendtext(struct ast_channel *c, const char *dest, const char *text, int ispdu) {
++static int zt_sendtext(struct ast_channel *c, const char *text) {
 + struct zt_pvt *p = c->tech_pvt;
 + if (!p) return -1;
 + if (p->sig == SIG_PRI) {
 +#ifdef HAVE_PRI
++      return zt_pri_sendtext(c, text);
++#endif
++ } else if (p->sig == SIG_GSM) {
++ } else {
++      return zt_tdd_sendtext(c, text);
++ }
++ return -1;
++}
++
++static int zt_sendmessage(struct ast_channel *c, const char *dest, const char *text, int ispdu) {
++struct zt_pvt *p = c->tech_pvt;
++ if (!p) return -1;
++ if (p->sig == SIG_PRI) {
++#ifdef HAVE_PRI
 +      if (ispdu) {
 +          ast_log(LOG_WARNING, "Dont know how to send PDU on ZAP ISDN channel\n");
 +          return -1;
@@ -8587,6 +7782,10 @@ Add or convert channel operations so they can use the unique ID.
 +     return zt_gsm_sendtext(c, dest, text, ispdu);
 +#endif
 + } else {
++      if (ispdu) {
++          ast_log(LOG_WARNING, "Dont know how to send PDU on ZAP channel\n");
++          return -1;
++      }
 +      return zt_tdd_sendtext(c, text);
 + }
 + return -1;
@@ -8606,80 +7805,194 @@ Add or convert channel operations so they can use the unique ID.
  AST_EXT_LIB_SETUP([IKSEMEL], [Iksemel Jabber Library], [iksemel])
  AST_EXT_LIB_SETUP([IMAP_TK], [UW IMAP Toolkit], [imap])
  AST_EXT_LIB_SETUP([ISDNNET], [ISDN4Linux Library], [isdnnet])
-@@ -466,6 +466,8 @@
+--- a/configure
++++ b/configure
+@@ -26600,6 +26600,188 @@ echo "$as_me: *** without explicitly spe
     fi
  fi
  
-+AST_EXT_LIB_CHECK([GSMAT], [gsmat], [gsm_new_call], [libgsmat.h])
-+
- AST_EXT_LIB_CHECK([IKSEMEL], [iksemel], [iks_start_sasl], [iksemel.h])
- if test "${PBX_IKSEMEL}" = 1; then
-diff -ur asterisk-1.4.17.org/channels/chan_zap.c asterisk-1.4.17/channels/chan_zap.c
---- asterisk-1.4.17.org/channels/chan_zap.c    2008-02-09 21:02:04.714653000 +0100
-+++ asterisk-1.4.17/channels/chan_zap.c        2008-02-09 21:05:07.690124195 +0100
-@@ -47,6 +47,7 @@
-       <depend>zaptel</depend>
-       <depend>tonezone</depend>
-       <depend>res_features</depend>
-+      <depend>gsmat</depend>
-       <use>pri</use>
-  ***/
-Tylko w asterisk-1.4.17/channels: chan_zap.c~
-diff -ur asterisk-1.4.17.org/channels/.chan_zap.moduleinfo asterisk-1.4.17/channels/.chan_zap.moduleinfo
---- asterisk-1.4.17.org/channels/.chan_zap.moduleinfo  2008-01-02 21:30:40.000000000 +0100
-+++ asterisk-1.4.17/channels/.chan_zap.moduleinfo      2008-02-09 21:04:54.802837479 +0100
-@@ -4,5 +4,6 @@
-       <depend>zaptel</depend>
-       <depend>tonezone</depend>
-       <depend>res_features</depend>
-+      <depend>gsmat</depend>
-       <use>pri</use>
- </member>
-Tylko w asterisk-1.4.17/channels: .chan_zap.moduleinfo~
-diff -ur asterisk-1.4.17.org/channels/.moduleinfo asterisk-1.4.17/channels/.moduleinfo
---- asterisk-1.4.17.org/channels/.moduleinfo   2008-01-02 21:30:40.000000000 +0100
-+++ asterisk-1.4.17/channels/.moduleinfo       2008-02-09 21:04:30.284991178 +0100
-@@ -50,6 +50,7 @@
-       <depend>zaptel</depend>
-       <depend>tonezone</depend>
-       <depend>res_features</depend>
-+      <depend>gsmat</depend>
-       <use>pri</use>
- </member>
- <member name="chan_vpb" displayname="" remove_on_change="channels/chan_vpb.oo channels/chan_vpb.so">
-Tylko w asterisk-1.4.17/channels: .moduleinfo~
-diff -ur asterisk-1.4.17.org/menuselect-tree asterisk-1.4.17/menuselect-tree
---- asterisk-1.4.17.org/menuselect-tree        2008-01-02 21:30:44.000000000 +0100
-+++ asterisk-1.4.17/menuselect-tree    2008-02-09 21:03:56.613371109 +0100
-@@ -247,6 +247,7 @@
-       <depend>zaptel</depend>
-       <depend>tonezone</depend>
-       <depend>res_features</depend>
-+      <depend>gsmat</depend>
-       <use>pri</use>
- </member>
- <member name="chan_vpb" displayname="" remove_on_change="channels/chan_vpb.oo channels/chan_vpb.so">
---- asterisk-1.4.17/makeopts.in.org    2008-02-09 21:32:11.948061985 +0100
-+++ asterisk-1.4.17/makeopts.in        2008-02-09 21:32:27.655480851 +0100
-@@ -83,6 +83,9 @@
- GSM_INCLUDE=@GSM_INCLUDE@
- GSM_LIB=@GSM_LIB@
-+GSMAT_INCLUDE=@GSMAT_INCLUDE@
-+GSMAT_LIB=@GSMAT_LIB@
-+
- GTK_INCLUDE=@GTK_INCLUDE@
- GTK_LIB=@GTK_LIB@
-
---- a/build_tools/menuselect-deps.in~  2007-09-14 17:50:49.000000000 +0200
-+++ b/build_tools/menuselect-deps.in   2008-02-09 21:30:40.933703503 +0100
-@@ -2,6 +2,7 @@
- CURL=@PBX_CURL@
- FREETDS=@PBX_FREETDS@
- GSM=@PBX_GSM@
-+GSMAT=@PBX_GSMAT@
- GTK=@PBX_GTK@
- GTK2=@PBX_GTK2@
- H323=@PBX_H323@
++{ echo "$as_me:$LINENO: checking for ${GSMAT_DIR}/include/libgsmat.h" >&5
++echo $ECHO_N "checking for ${GSMAT_DIR}/include/libgsmat.h... $ECHO_C" >&6; }
++if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
++  echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++  eval "$as_ac_Header=\$ac_header_preproc"
++fi
++ac_res=`eval echo '${'$as_ac_Header'}'`
++             { echo "$as_me:$LINENO: result: $ac_res" >&5
++echo "${ECHO_T}$ac_res" >&6; }
++
++if test `eval echo '${'$as_ac_Header'}'` = yes; then
++  GSMAT_HEADER_FOUND=1
++else
++  GSMAT_HEADER_FOUND=0
++fi
++
++
++
++   if test "${GSMAT_HEADER_FOUND}" = "yes"; then
++      GSMAT_LIB="-lgsmat "
++      GSMAT_HEADER_FOUND="1"
++      if test "x${GSMAT_DIR}" != "x"; then
++         GSMAT_LIB="${pbxlibdir} ${GSMAT_LIB}"
++       GSMAT_INCLUDE="-I${GSMAT_DIR}/include"
++       fi
++       CPPFLAGS="${saved_cppflags}"
++      else
++       if test "xlibgsmat.h" != "x" ; then
++            if test "${ac_cv_header_libpri_h+set}" = set; then
++  { echo "$as_me:$LINENO: checking for libgsmat.h" >&5
++echo $ECHO_N "checking for libgsmat.h... $ECHO_C" >&6; }
++if test "${ac_cv_header_libgsmat_h+set}" = set; then
++  echo $ECHO_N "(cached) $ECHO_C" >&6
++fi
++{ echo "$as_me:$LINENO: result: $ac_cv_header_libgsmat_h" >&5
++echo "${ECHO_T}$ac_cv_header_libgsmat_h" >&6; }
++else
++  # Is the header compilable?
++{ echo "$as_me:$LINENO: checking libgsmat.h usability" >&5
++echo $ECHO_N "checking libgsmat.h usability... $ECHO_C" >&6; }
++cat >conftest.$ac_ext <<_ACEOF
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
++$ac_includes_default
++#include <libgsmat.h>
++_ACEOF
++rm -f conftest.$ac_objext
++if { (ac_try="$ac_compile"
++case "(($ac_try" in
++  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++  *) ac_try_echo=$ac_try;;
++esac
++eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
++  (eval "$ac_compile") 2>conftest.er1
++  ac_status=$?
++  grep -v '^ *+' conftest.er1 >conftest.err
++  rm -f conftest.er1
++  cat conftest.err >&5
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); } && {
++       test -z "$ac_c_werror_flag" ||
++       test ! -s conftest.err
++       } && test -s conftest.$ac_objext; then
++  ac_header_compiler=yes
++else
++  echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++      ac_header_compiler=no
++fi
++
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
++echo "${ECHO_T}$ac_header_compiler" >&6; }
++
++# Is the header present?
++{ echo "$as_me:$LINENO: checking libgsmat.h presence" >&5
++echo $ECHO_N "checking libgsmat.h presence... $ECHO_C" >&6; }
++cat >conftest.$ac_ext <<_ACEOF
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
++#include <libgsmat.h>
++_ACEOF
++if { (ac_try="$ac_cpp conftest.$ac_ext"
++case "(($ac_try" in
++  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++  *) ac_try_echo=$ac_try;;
++esac
++eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
++  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
++  ac_status=$?
++  grep -v '^ *+' conftest.er1 >conftest.err
++  rm -f conftest.er1
++  cat conftest.err >&5
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); } >/dev/null && {
++       test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
++       test ! -s conftest.err
++       }; then
++  ac_header_preproc=yes
++else
++  echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++  ac_header_preproc=no
++fi
++
++rm -f conftest.err conftest.$ac_ext
++{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
++echo "${ECHO_T}$ac_header_preproc" >&6; }
++
++# So?  What about this header?
++case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
++  yes:no: )
++    { echo "$as_me:$LINENO: WARNING: libgsmat.h: accepted by the compiler, rejected by the preprocessor!" >&5
++echo "$as_me: WARNING: libgsmat.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
++    { echo "$as_me:$LINENO: WARNING: libgsmat.h: proceeding with the compiler's result" >&5
++echo "$as_me: WARNING: libgsmat.h: proceeding with the compiler's result" >&2;}
++    ac_header_preproc=yes
++    ;;
++  no:yes:* )
++    { echo "$as_me:$LINENO: WARNING: libgsmat.h: present but cannot be compiled" >&5
++echo "$as_me: WARNING: libgsmat.h: present but cannot be compiled" >&2;}
++    { echo "$as_me:$LINENO: WARNING: libgsmat.h:     check for missing prerequisite headers?" >&5
++echo "$as_me: WARNING: libgsmat.h:     check for missing prerequisite headers?" >&2;}
++    { echo "$as_me:$LINENO: WARNING: libgsmat.h: see the Autoconf documentation" >&5
++echo "$as_me: WARNING: libgsmat.h: see the Autoconf documentation" >&2;}
++    { echo "$as_me:$LINENO: WARNING: libgsmat.h:     section \"Present But Cannot Be Compiled\"" >&5
++echo "$as_me: WARNING: libgsmat.h:     section \"Present But Cannot Be Compiled\"" >&2;}
++    { echo "$as_me:$LINENO: WARNING: libgsmat.h: proceeding with the preprocessor's result" >&5
++echo "$as_me: WARNING: libgsmat.h: proceeding with the preprocessor's result" >&2;}
++    { echo "$as_me:$LINENO: WARNING: libgsmat.h: in the future, the compiler will take precedence" >&5
++echo "$as_me: WARNING: libgsmat.h: in the future, the compiler will take precedence" >&2;}
++
++    ;;
++esac
++{ echo "$as_me:$LINENO: checking for libgsmat.h" >&5
++echo $ECHO_N "checking for libgsmat.h... $ECHO_C" >&6; }
++if test "${ac_cv_header_libgsmat_h+set}" = set; then
++  echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++  ac_cv_header_libgsmat_h=$ac_header_preproc
++fi
++{ echo "$as_me:$LINENO: result: $ac_cv_header_libgsmat_h" >&5
++echo "${ECHO_T}$ac_cv_header_libgsmat_h" >&6; }
++
++fi
++
++
++       fi
++      fi
++      if test "x${GSMAT_HEADER_FOUND}" = "x0" ; then
++         if test -n "${GSMAT_MANDATORY}" ;
++         then
++            { echo "$as_me:$LINENO: ***" >&5
++echo "$as_me: ***" >&6;}
++            { echo "$as_me:$LINENO: *** It appears that you do not have the GSMAT development package installed." >&5
++echo "$as_me: *** It appears that you do not have the GSMAT development package installed." >&6;}
++            { echo "$as_me:$LINENO: *** Please install it to include ${GSMAT_DESCRIP} support, or re-run configure" >&5
++echo "$as_me: *** Please install it to include ${GSMAT_DESCRIP} support, or re-run configure" >&6;}
++            { echo "$as_me:$LINENO: *** without explicitly specifying --with-${GSMAT_OPTION}" >&5
++echo "$as_me: *** without explicitly specifying --with-${GSMAT_OPTION}" >&6;}
++            exit 1
++         fi
++         GSMAT_LIB=""
++         GSMAT_INCLUDE=""
++         PBX_GSMAT=0
++      else
++         PBX_GSMAT=1
++
++cat >>confdefs.h <<_ACEOF
++#define HAVE_GSMAT 1
++_ACEOF
++
++fi
+ if test "${USE_PWLIB}" != "no"; then
+       if test -n "${PWLIB_DIR}"; then
This page took 1.351788 seconds and 4 git commands to generate.