Add a massive set of changes for converting to use the ast_debug() macro.
[asterisk/asterisk.git] / channels / chan_phone.c
index 8f732e9..e33d1a1 100644 (file)
  * \ingroup channel_drivers
  */
 
+/*** MODULEINFO
+       <depend>ixjuser</depend>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 #include <arpa/inet.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
+#include <signal.h>
 #include <linux/telephony.h>
 /* Still use some IXJ specific stuff */
 #include <linux/version.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-# include <linux/compiler.h>
-#endif
 #include <linux/ixjuser.h>
 
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
 #include "asterisk/lock.h"
 #include "asterisk/channel.h"
 #include "asterisk/config.h"
@@ -58,6 +60,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/utils.h"
 #include "asterisk/callerid.h"
 #include "asterisk/causes.h"
+#include "asterisk/stringfields.h"
+#include "asterisk/musiconhold.h"
+
 #include "DialTone.h"
 
 #ifdef QTI_PHONEJACK_TJ_PCI    /* check for the newer quicknet driver v.3.1.0 which has this symbol */
@@ -80,8 +85,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #define PHONE_MAX_BUF 480
 #define DEFAULT_GAIN 0x100
 
-static const char desc[] = "Linux Telephony API Support";
-static const char type[] = "Phone";
 static const char tdesc[] = "Standard Linux Telephony API Driver";
 static const char config[] = "phone.conf";
 
@@ -90,15 +93,12 @@ static char context[AST_MAX_EXTENSION] = "default";
 
 /* Default language */
 static char language[MAX_LANGUAGE] = "";
-static int usecnt =0;
 
 static int echocancel = AEC_OFF;
 
 static int silencesupression = 0;
 
-static int prefformat = AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW;
-
-AST_MUTEX_DEFINE_STATIC(usecnt_lock);
+static int prefformat = AST_FORMAT_G729A | AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW;
 
 /* Protect the interface list (of phone_pvt's) */
 AST_MUTEX_DEFINE_STATIC(iflock);
@@ -106,6 +106,9 @@ AST_MUTEX_DEFINE_STATIC(iflock);
 /* 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);
+
+/* Boolean value whether the monitoring thread shall continue. */
+static unsigned int monitor;
    
 /* This is the thread for the monitor which checks for input on the channels
    which are not currently in use.  */
@@ -118,8 +121,9 @@ static int restart_monitor(void);
    
 #define MODE_DIALTONE  1
 #define MODE_IMMEDIATE 2
-#define MODE_FXO               3
+#define MODE_FXO       3
 #define MODE_FXS        4
+#define MODE_SIGMA      5
 
 static struct phone_pvt {
        int fd;                                                 /* Raw file descriptor for this device */
@@ -151,7 +155,8 @@ static char cid_num[AST_MAX_EXTENSION];
 static char cid_name[AST_MAX_EXTENSION];
 
 static struct ast_channel *phone_request(const char *type, int format, void *data, int *cause);
-static int phone_digit(struct ast_channel *ast, char digit);
+static int phone_digit_begin(struct ast_channel *ast, char digit);
+static int phone_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
 static int phone_call(struct ast_channel *ast, char *dest, int timeout);
 static int phone_hangup(struct ast_channel *ast);
 static int phone_answer(struct ast_channel *ast);
@@ -160,14 +165,15 @@ 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_fixup(struct ast_channel *old, struct ast_channel *new);
-static int phone_indicate(struct ast_channel *chan, int condition);
+static int phone_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
 
 static const struct ast_channel_tech phone_tech = {
-       .type = type,
+       .type = "Phone",
        .description = tdesc,
-       .capabilities = AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW,
+       .capabilities = AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_G729A,
        .requester = phone_request,
-       .send_digit = phone_digit,
+       .send_digit_begin = phone_digit_begin,
+       .send_digit_end = phone_digit_end,
        .call = phone_call,
        .hangup = phone_hangup,
        .answer = phone_answer,
@@ -179,10 +185,11 @@ static const struct ast_channel_tech phone_tech = {
 };
 
 static struct ast_channel_tech phone_tech_fxs = {
-       .type = type,
+       .type = "Phone",
        .description = tdesc,
        .requester = phone_request,
-       .send_digit = phone_digit,
+       .send_digit_begin = phone_digit_begin,
+       .send_digit_end = phone_digit_end,
        .call = phone_call,
        .hangup = phone_hangup,
        .answer = phone_answer,
@@ -197,11 +204,11 @@ static struct ast_channel_tech phone_tech_fxs = {
 
 static struct ast_channel_tech *cur_tech;
 
-static int phone_indicate(struct ast_channel *chan, int condition)
+static int phone_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
 {
        struct phone_pvt *p = chan->tech_pvt;
        int res=-1;
-       ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
+       ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
        switch(condition) {
                case AST_CONTROL_FLASH:
                        ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_ON_HOOK);
@@ -210,6 +217,12 @@ static int phone_indicate(struct ast_channel *chan, int condition)
                        p->lastformat = -1;
                        res = 0;
                        break;
+               case AST_CONTROL_HOLD:
+                       ast_moh_start(chan, data, NULL);
+                       break;
+               case AST_CONTROL_UNHOLD:
+                       ast_moh_stop(chan);
+                       break;
                default:
                        ast_log(LOG_WARNING, "Condition %d is not supported on channel %s\n", condition, chan->name);
        }
@@ -224,12 +237,18 @@ static int phone_fixup(struct ast_channel *old, struct ast_channel *new)
        return 0;
 }
 
-static int phone_digit(struct ast_channel *ast, char digit)
+static int phone_digit_begin(struct ast_channel *chan, char digit)
+{
+       /* XXX Modify this callback to let Asterisk support controlling the length of DTMF */
+       return 0;
+}
+
+static int phone_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
 {
        struct phone_pvt *p;
        int outdigit;
        p = ast->tech_pvt;
-       ast_log(LOG_NOTICE, "Dialed %c\n", digit);
+       ast_debug(1, "Dialed %c\n", digit);
        switch(digit) {
        case '0':
        case '1':
@@ -260,7 +279,7 @@ static int phone_digit(struct ast_channel *ast, char digit)
                ast_log(LOG_WARNING, "Unknown digit '%c'\n", digit);
                return -1;
        }
-       ast_log(LOG_NOTICE, "Dialed %d\n", outdigit);
+       ast_debug(1, "Dialed %d\n", outdigit);
        ioctl(p->fd, PHONE_PLAY_TONE, outdigit);
        p->lastformat = -1;
        return 0;
@@ -287,12 +306,12 @@ static int phone_call(struct ast_channel *ast, char *dest, int timeout)
        }
        /* the standard format of ast->callerid is:  "name" <number>, but not always complete */
        if (ast_strlen_zero(ast->cid.cid_name))
-               strncpy(cid.name, DEFAULT_CALLER_ID, sizeof(cid.name) - 1);
+               strcpy(cid.name, DEFAULT_CALLER_ID);
        else
-               strncpy(cid.name, ast->cid.cid_name, sizeof(cid.name) - 1);
+               ast_copy_string(cid.name, ast->cid.cid_name, sizeof(cid.name));
 
        if (ast->cid.cid_num) 
-               strncpy(cid.number, ast->cid.cid_num, sizeof(cid.number) - 1);
+               ast_copy_string(cid.number, ast->cid.cid_num, sizeof(cid.number));
 
        p = ast->tech_pvt;
 
@@ -300,8 +319,7 @@ static int phone_call(struct ast_channel *ast, char *dest, int timeout)
                ast_log(LOG_WARNING, "phone_call called on %s, neither down nor reserved\n", ast->name);
                return -1;
        }
-       if (option_debug)
-               ast_log(LOG_DEBUG, "Ringing %s on %s (%d)\n", dest, ast->name, ast->fds[0]);
+       ast_debug(1, "Ringing %s on %s (%d)\n", dest, ast->name, ast->fds[0]);
 
        start = IXJ_PHONE_RING_START(cid);
        if (start == -1)
@@ -313,7 +331,7 @@ static int phone_call(struct ast_channel *ast, char *dest, int timeout)
                {
                  digit++;
                  while (*digit)
-                   phone_digit(ast, *digit++);
+                   phone_digit_end(ast, *digit++, 0);
                }
        }
  
@@ -326,8 +344,7 @@ static int phone_hangup(struct ast_channel *ast)
 {
        struct phone_pvt *p;
        p = ast->tech_pvt;
-       if (option_debug)
-               ast_log(LOG_DEBUG, "phone_hangup(%s)\n", ast->name);
+       ast_debug(1, "phone_hangup(%s)\n", ast->name);
        if (!ast->tech_pvt) {
                ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
                return 0;
@@ -345,14 +362,13 @@ static int phone_hangup(struct ast_channel *ast)
 
        /* If it's an FXO, hang them up */
        if (p->mode == MODE_FXO) {
-               if (ioctl(p->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK)) 
-                       ast_log(LOG_DEBUG, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",ast->name, strerror(errno));
+               if (ioctl(p->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK))
+                       ast_debug(1, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",ast->name, strerror(errno));
        }
 
        /* If they're off hook, give a busy signal */
        if (ioctl(p->fd, PHONE_HOOKSTATE)) {
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Got hunghup, giving busy signal\n");
+               ast_debug(1, "Got hunghup, giving busy signal\n");
                ioctl(p->fd, PHONE_BUSY);
                p->cpt = 1;
        }
@@ -363,12 +379,7 @@ static int phone_hangup(struct ast_channel *ast)
        p->dialtone = 0;
        memset(p->ext, 0, sizeof(p->ext));
        ((struct phone_pvt *)(ast->tech_pvt))->owner = NULL;
-       ast_mutex_lock(&usecnt_lock);
-       usecnt--;
-       if (usecnt < 0) 
-               ast_log(LOG_WARNING, "Usecnt < 0???\n");
-       ast_mutex_unlock(&usecnt_lock);
-       ast_update_use_count();
+       ast_module_unref(ast_module_info->self);
        if (option_verbose > 2) 
                ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
        ast->tech_pvt = NULL;
@@ -383,8 +394,17 @@ static int phone_setup(struct ast_channel *ast)
        p = ast->tech_pvt;
        ioctl(p->fd, PHONE_CPT_STOP);
        /* Nothing to answering really, just start recording */
-       if (ast->rawreadformat == AST_FORMAT_G723_1) {
-               /* Prefer g723 */
+       if (ast->rawreadformat == AST_FORMAT_G729A) {
+               /* Prefer g729 */
+               ioctl(p->fd, PHONE_REC_STOP);
+               if (p->lastinput != AST_FORMAT_G729A) {
+                       p->lastinput = AST_FORMAT_G729A;
+                       if (ioctl(p->fd, PHONE_REC_CODEC, G729)) {
+                               ast_log(LOG_WARNING, "Failed to set codec to g729\n");
+                               return -1;
+                       }
+               }
+        } else if (ast->rawreadformat == AST_FORMAT_G723_1) {
                ioctl(p->fd, PHONE_REC_STOP);
                if (p->lastinput != AST_FORMAT_G723_1) {
                        p->lastinput = AST_FORMAT_G723_1;
@@ -441,14 +461,13 @@ static int phone_answer(struct ast_channel *ast)
        p = ast->tech_pvt;
        /* In case it's a LineJack, take it off hook */
        if (p->mode == MODE_FXO) {
-               if (ioctl(p->fd, PHONE_PSTN_SET_STATE, PSTN_OFF_HOOK)) 
-                       ast_log(LOG_DEBUG, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n", ast->name, strerror(errno));
+               if (ioctl(p->fd, PHONE_PSTN_SET_STATE, PSTN_OFF_HOOK))
+                       ast_debug(1, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n", ast->name, strerror(errno));
                else
-                       ast_log(LOG_DEBUG, "Took linejack off hook\n");
+                       ast_debug(1, "Took linejack off hook\n");
        }
        phone_setup(ast);
-       if (option_debug)
-               ast_log(LOG_DEBUG, "phone_answer(%s)\n", ast->name);
+       ast_debug(1, "phone_answer(%s)\n", ast->name);
        ast->rings = 0;
        ast_setstate(ast, AST_STATE_UP);
        return 0;
@@ -479,15 +498,14 @@ static struct ast_frame  *phone_exception(struct ast_channel *ast)
        p->fr.datalen = 0;
        p->fr.samples = 0;
        p->fr.data =  NULL;
-       p->fr.src = type;
+       p->fr.src = "Phone";
        p->fr.offset = 0;
        p->fr.mallocd=0;
        p->fr.delivery = ast_tv(0,0);
        
        phonee.bytes = ioctl(p->fd, PHONE_EXCEPTION);
        if (phonee.bits.dtmf_ready)  {
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "phone_exception(): DTMF\n");
+               ast_debug(1, "phone_exception(): DTMF\n");
        
                /* We've got a digit -- Just handle this nicely and easily */
                digit =  ioctl(p->fd, PHONE_GET_DTMF_ASCII);
@@ -496,12 +514,10 @@ static struct ast_frame  *phone_exception(struct ast_channel *ast)
                return &p->fr;
        }
        if (phonee.bits.hookstate) {
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Hookstate changed\n");
+               ast_debug(1, "Hookstate changed\n");
                res = ioctl(p->fd, PHONE_HOOKSTATE);
                /* See if we've gone on hook, if so, notify by returning NULL */
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "New hookstate: %d\n", res);
+               ast_debug(1, "New hookstate: %d\n", res);
                if (!res && (p->mode != MODE_FXO))
                        return NULL;
                else {
@@ -541,7 +557,7 @@ static struct ast_frame  *phone_read(struct ast_channel *ast)
        p->fr.datalen = 0;
        p->fr.samples = 0;
        p->fr.data =  NULL;
-       p->fr.src = type;
+       p->fr.src = "Phone";
        p->fr.offset = 0;
        p->fr.mallocd=0;
        p->fr.delivery = ast_tv(0,0);
@@ -647,7 +663,7 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
                return 0;
        }
        if (!(frame->subclass &
-               (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW)) && 
+               (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_G729A)) && 
            p->mode != MODE_FXS) {
                ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
                return -1;
@@ -664,7 +680,30 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
                return 0;
        }
 #endif 
-       if (frame->subclass == AST_FORMAT_G723_1) {
+       if (frame->subclass == AST_FORMAT_G729A) {
+               if (p->lastformat != AST_FORMAT_G729A) {
+                       ioctl(p->fd, PHONE_PLAY_STOP);
+                       ioctl(p->fd, PHONE_REC_STOP);
+                       if (ioctl(p->fd, PHONE_PLAY_CODEC, G729)) {
+                               ast_log(LOG_WARNING, "Unable to set G729 mode\n");
+                               return -1;
+                       }
+                       if (ioctl(p->fd, PHONE_REC_CODEC, G729)) {
+                               ast_log(LOG_WARNING, "Unable to set G729 mode\n");
+                               return -1;
+                       }
+                       p->lastformat = AST_FORMAT_G729A;
+                       p->lastinput = AST_FORMAT_G729A;
+                       /* Reset output buffer */
+                       p->obuflen = 0;
+                       codecset = 1;
+               }
+               if (frame->datalen > 80) {
+                       ast_log(LOG_WARNING, "Frame size too large for G.729 (%d bytes)\n", frame->datalen);
+                       return -1;
+               }
+               maxfr = 80;
+        } else if (frame->subclass == AST_FORMAT_G723_1) {
                if (p->lastformat != AST_FORMAT_G723_1) {
                        ioctl(p->fd, PHONE_PLAY_STOP);
                        ioctl(p->fd, PHONE_REC_STOP);
@@ -812,11 +851,9 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *conte
 {
        struct ast_channel *tmp;
        struct phone_codec_data codec;
-       tmp = ast_channel_alloc(1);
+       tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", i->ext, i->context, 0, "Phone/%s", i->dev + 5);
        if (tmp) {
                tmp->tech = cur_tech;
-               snprintf(tmp->name, sizeof(tmp->name), "Phone/%s", i->dev + 5);
-               tmp->type = type;
                tmp->fds[0] = i->fd;
                /* XXX Switching formats silently causes kernel panics XXX */
                if (i->mode == MODE_FXS &&
@@ -838,26 +875,26 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *conte
                        tmp->rawreadformat = prefformat;
                        tmp->rawwriteformat = prefformat;
                }
-               ast_setstate(tmp, state);
+               /* no need to call ast_setstate: the channel_alloc already did its job */
                if (state == AST_STATE_RING)
                        tmp->rings = 1;
                tmp->tech_pvt = i;
-               strncpy(tmp->context, context, sizeof(tmp->context)-1);
+               ast_copy_string(tmp->context, context, sizeof(tmp->context));
                if (!ast_strlen_zero(i->ext))
-                       strncpy(tmp->exten, i->ext, sizeof(tmp->exten)-1);
+                       ast_copy_string(tmp->exten, i->ext, sizeof(tmp->exten));
                else
-                       strncpy(tmp->exten, "s",  sizeof(tmp->exten) - 1);
+                       strcpy(tmp->exten, "s");
                if (!ast_strlen_zero(i->language))
-                       strncpy(tmp->language, i->language, sizeof(tmp->language)-1);
-               if (!ast_strlen_zero(i->cid_num))
-                       tmp->cid.cid_num = strdup(i->cid_num);
-               if (!ast_strlen_zero(i->cid_name))
-                       tmp->cid.cid_name = strdup(i->cid_name);
+                       ast_string_field_set(tmp, language, i->language);
+
+               /* Don't use ast_set_callerid() here because it will
+                * generate a NewCallerID event before the NewChannel event */
+               tmp->cid.cid_num = ast_strdup(i->cid_num);
+               tmp->cid.cid_ani = ast_strdup(i->cid_num);
+               tmp->cid.cid_name = ast_strdup(i->cid_name);
+
                i->owner = tmp;
-               ast_mutex_lock(&usecnt_lock);
-               usecnt++;
-               ast_mutex_unlock(&usecnt_lock);
-               ast_update_use_count();
+               ast_module_ref(ast_module_info->self);
                if (state != AST_STATE_DOWN) {
                        if (state == AST_STATE_RING) {
                                ioctl(tmp->fds[0], PHONE_RINGBACK);
@@ -892,12 +929,12 @@ static void phone_check_exception(struct phone_pvt *i)
        union telephony_exception phonee;
        /* XXX Do something XXX */
 #if 0
-       ast_log(LOG_DEBUG, "Exception!\n");
+       ast_debug(1, "Exception!\n");
 #endif
        phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION);
        if (phonee.bits.dtmf_ready)  {
                digit[0] = ioctl(i->fd, PHONE_GET_DTMF_ASCII);
-               if (i->mode == MODE_DIALTONE || i->mode == MODE_FXS) {
+               if (i->mode == MODE_DIALTONE || i->mode == MODE_FXS || i->mode == MODE_SIGMA) {
                        ioctl(i->fd, PHONE_PLAY_STOP);
                        ioctl(i->fd, PHONE_REC_STOP);
                        ioctl(i->fd, PHONE_CPT_STOP);
@@ -920,8 +957,7 @@ static void phone_check_exception(struct phone_pvt *i)
                                        /* XXX This should probably be justified better XXX */
                                }  else if (!ast_canmatch_extension(NULL, "default", i->ext, 1, i->cid_num)) {
                                        /* It's not a valid extension, give a busy signal */
-                                       if (option_debug)
-                                               ast_log(LOG_DEBUG, "%s can't match anything in %s or default\n", i->ext, i->context);
+                                       ast_debug(1, "%s can't match anything in %s or default\n", i->ext, i->context);
                                        ioctl(i->fd, PHONE_BUSY);
                                        i->cpt = 1;
                                }
@@ -937,10 +973,7 @@ static void phone_check_exception(struct phone_pvt *i)
                        if (i->mode == MODE_IMMEDIATE) {
                                phone_new(i, AST_STATE_RING, i->context);
                        } else if (i->mode == MODE_DIALTONE) {
-                               ast_mutex_lock(&usecnt_lock);
-                               usecnt++;
-                               ast_mutex_unlock(&usecnt_lock);
-                               ast_update_use_count();
+                               ast_module_ref(ast_module_info->self);
                                /* Reset the extension */
                                i->ext[0] = '\0';
                                /* Play the dialtone */
@@ -949,14 +982,17 @@ static void phone_check_exception(struct phone_pvt *i)
                                ioctl(i->fd, PHONE_PLAY_CODEC, ULAW);
                                ioctl(i->fd, PHONE_PLAY_START);
                                i->lastformat = -1;
+                       } else if (i->mode == MODE_SIGMA) {
+                               ast_module_ref(ast_module_info->self);
+                               /* Reset the extension */
+                               i->ext[0] = '\0';
+                               /* Play the dialtone */
+                               i->dialtone++;
+                               ioctl(i->fd, PHONE_DIALTONE);
                        }
                } else {
-                       if (i->dialtone) {
-                               ast_mutex_lock(&usecnt_lock);
-                               usecnt--;
-                               ast_mutex_unlock(&usecnt_lock);
-                               ast_update_use_count();
-                       }
+                       if (i->dialtone)
+                               ast_module_unref(ast_module_info->self);
                        memset(i->ext, 0, sizeof(i->ext));
                        if (i->cpt)
                        {
@@ -990,22 +1026,12 @@ static void *do_monitor(void *data)
        int dotone;
        /* This thread monitors all the frame relay interfaces which are not yet in use
           (and thus do not have a separate thread) indefinitely */
-       /* From here on out, we die whenever asked */
-       if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
-               ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
-               return NULL;
-       }
-       for(;;) {
+       while (monitor) {
                /* Don't let anybody kill us right away.  Nobody should lock the interface list
                   and wait for the monitor list, but the other way around is okay. */
-               if (ast_mutex_lock(&monlock)) {
-                       ast_log(LOG_ERROR, "Unable to grab monitor lock\n");
-                       return NULL;
-               }
                /* Lock the interface list */
                if (ast_mutex_lock(&iflock)) {
                        ast_log(LOG_ERROR, "Unable to grab interface lock\n");
-                       ast_mutex_unlock(&monlock);
                        return NULL;
                }
                /* Build the stuff we're going to select on, that is the socket of every
@@ -1015,7 +1041,7 @@ static void *do_monitor(void *data)
                FD_ZERO(&efds);
                i = iflist;
                dotone = 0;
-               while(i) {
+               while (i) {
                        if (FD_ISSET(i->fd, &rfds)) 
                                ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev);
                        if (!i->owner) {
@@ -1024,7 +1050,7 @@ static void *do_monitor(void *data)
                                FD_SET(i->fd, &efds);
                                if (i->fd > n)
                                        n = i->fd;
-                               if (i->dialtone) {
+                               if (i->dialtone && i->mode != MODE_SIGMA) {
                                        /* Remember we're going to have to come back and play
                                           more dialtones */
                                        if (ast_tvzero(tv)) {
@@ -1041,11 +1067,8 @@ static void *do_monitor(void *data)
                /* Okay, now that we know what to do, release the interface lock */
                ast_mutex_unlock(&iflock);
 
-               /* And from now on, we're okay to be killed, so release the monitor lock as well */
-               ast_mutex_unlock(&monlock);
-
                /* Wait indefinitely for something to happen */
-               if (dotone) {
+               if (dotone && i->mode != MODE_SIGMA) {
                        /* If we're ready to recycle the time, set it to 30 ms */
                        tonepos += 240;
                        if (tonepos >= sizeof(DialTone))
@@ -1061,7 +1084,7 @@ static void *do_monitor(void *data)
                }
                /* Okay, select has finished.  Let's see what happened.  */
                if (res < 0) {
-                       ast_log(LOG_WARNING, "select return %d: %s\n", res, strerror(errno));
+                       ast_debug(1, "select return %d: %s\n", res, strerror(errno));
                        continue;
                }
                /* If there are no fd's changed, just continue, it's probably time
@@ -1092,7 +1115,6 @@ static void *do_monitor(void *data)
                }
                ast_mutex_unlock(&iflock);
        }
-       /* Never reached */
        return NULL;
        
 }
@@ -1113,18 +1135,19 @@ static int restart_monitor()
        }
        if (monitor_thread != AST_PTHREADT_NULL) {
                if (ast_mutex_lock(&iflock)) {
-                 ast_mutex_unlock(&monlock);
-                 ast_log(LOG_WARNING, "Unable to lock the interface list\n");
-                 return -1;
+                       ast_mutex_unlock(&monlock);
+                       ast_log(LOG_WARNING, "Unable to lock the interface list\n");
+                       return -1;
                }
-               pthread_cancel(monitor_thread);
-#if 0
+               monitor = 0;
+               while (pthread_kill(monitor_thread, SIGURG) == 0)
+                       sched_yield();
                pthread_join(monitor_thread, NULL);
-#endif
                ast_mutex_unlock(&iflock);
        }
+       monitor = 1;
        /* Start a new monitor */
-       if (ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
+       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
                ast_mutex_unlock(&monlock);
                ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
                return -1;
@@ -1139,28 +1162,29 @@ static struct phone_pvt *mkif(char *iface, int mode, int txgain, int rxgain)
        struct phone_pvt *tmp;
        int flags;      
        
-       tmp = malloc(sizeof(struct phone_pvt));
+       tmp = ast_calloc(1, sizeof(*tmp));
        if (tmp) {
                tmp->fd = open(iface, O_RDWR);
                if (tmp->fd < 0) {
                        ast_log(LOG_WARNING, "Unable to open '%s'\n", iface);
-                       free(tmp);
+                       ast_free(tmp);
                        return NULL;
                }
                if (mode == MODE_FXO) {
-                       if (ioctl(tmp->fd, IXJCTL_PORT, PORT_PSTN)) 
-                               ast_log(LOG_DEBUG, "Unable to set port to PSTN\n");
+                       if (ioctl(tmp->fd, IXJCTL_PORT, PORT_PSTN)) {
+                               ast_debug(1, "Unable to set port to PSTN\n");
+                       }
                } else {
                        if (ioctl(tmp->fd, IXJCTL_PORT, PORT_POTS)) 
                                 if (mode != MODE_FXS)
-                                     ast_log(LOG_DEBUG, "Unable to set port to POTS\n");
+                                     ast_debug(1, "Unable to set port to POTS\n");
                }
                ioctl(tmp->fd, PHONE_PLAY_STOP);
                ioctl(tmp->fd, PHONE_REC_STOP);
                ioctl(tmp->fd, PHONE_RING_STOP);
                ioctl(tmp->fd, PHONE_CPT_STOP);
-               if (ioctl(tmp->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK)) 
-                       ast_log(LOG_DEBUG, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",iface, strerror(errno));
+               if (ioctl(tmp->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK))
+                       ast_debug(1, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",iface, strerror(errno));
                if (echocancel != AEC_OFF)
                        ioctl(tmp->fd, IXJCTL_AEC_START, echocancel);
                if (silencesupression) 
@@ -1176,15 +1200,15 @@ static struct phone_pvt *mkif(char *iface, int mode, int txgain, int rxgain)
                tmp->lastinput = -1;
                tmp->ministate = 0;
                memset(tmp->ext, 0, sizeof(tmp->ext));
-               strncpy(tmp->language, language, sizeof(tmp->language)-1);
-               strncpy(tmp->dev, iface, sizeof(tmp->dev)-1);
-               strncpy(tmp->context, context, sizeof(tmp->context)-1);
+               ast_copy_string(tmp->language, language, sizeof(tmp->language));
+               ast_copy_string(tmp->dev, iface, sizeof(tmp->dev));
+               ast_copy_string(tmp->context, context, sizeof(tmp->context));
                tmp->next = NULL;
                tmp->obuflen = 0;
                tmp->dialtone = 0;
                tmp->cpt = 0;
-               strncpy(tmp->cid_num, cid_num, sizeof(tmp->cid_num)-1);
-               strncpy(tmp->cid_name, cid_name, sizeof(tmp->cid_name)-1);
+               ast_copy_string(tmp->cid_num, cid_num, sizeof(tmp->cid_num));
+               ast_copy_string(tmp->cid_name, cid_name, sizeof(tmp->cid_name));
                tmp->txgain = txgain;
                ioctl(tmp->fd, PHONE_PLAY_VOLUME, tmp->txgain);
                tmp->rxgain = rxgain;
@@ -1208,7 +1232,7 @@ static struct ast_channel *phone_request(const char *type, int format, void *dat
        p = iflist;
        while(p) {
                if (p->mode == MODE_FXS ||
-                   format & (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW)) {
+                   format & (AST_FORMAT_G729A | AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW)) {
                    size_t length = strlen(p->dev + 5);
                if (strncmp(name, p->dev + 5, length) == 0 &&
                    !isalnum(name[length])) {
@@ -1225,7 +1249,7 @@ static struct ast_channel *phone_request(const char *type, int format, void *dat
        restart_monitor();
        if (tmp == NULL) {
                oldformat = format;
-               format &= (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW);
+               format &= (AST_FORMAT_G729A | AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW);
                if (!format) {
                        ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat);
                        return NULL;
@@ -1278,7 +1302,9 @@ static int __unload_module(void)
        }
        if (!ast_mutex_lock(&monlock)) {
                if (monitor_thread > AST_PTHREADT_NULL) {
-                       pthread_cancel(monitor_thread);
+                       monitor = 0;
+                       while (pthread_kill(monitor_thread, SIGURG) == 0)
+                               sched_yield();
                        pthread_join(monitor_thread, NULL);
                }
                monitor_thread = AST_PTHREADT_STOP;
@@ -1298,7 +1324,7 @@ static int __unload_module(void)
                        pl = p;
                        p = p->next;
                        /* Free associated memory */
-                       free(pl);
+                       ast_free(pl);
                }
                iflist = NULL;
                ast_mutex_unlock(&iflock);
@@ -1310,12 +1336,12 @@ static int __unload_module(void)
        return 0;
 }
 
-int unload_module(void)
+static int unload_module(void)
 {
        return __unload_module();
 }
 
-int load_module()
+static int load_module(void)
 {
        struct ast_config *cfg;
        struct ast_variable *v;
@@ -1327,7 +1353,7 @@ int load_module()
        /* We *must* have a config file otherwise stop immediately */
        if (!cfg) {
                ast_log(LOG_ERROR, "Unable to load config %s\n", config);
-               return -1;
+               return AST_MODULE_LOAD_DECLINE;
        }
        if (ast_mutex_lock(&iflock)) {
                /* It's a little silly to lock it, but we mind as well just to be sure */
@@ -1353,12 +1379,14 @@ int load_module()
                } else if (!strcasecmp(v->name, "silencesupression")) {
                        silencesupression = ast_true(v->value);
                } else if (!strcasecmp(v->name, "language")) {
-                       strncpy(language, v->value, sizeof(language)-1);
+                       ast_copy_string(language, v->value, sizeof(language));
                } else if (!strcasecmp(v->name, "callerid")) {
                        ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
                } else if (!strcasecmp(v->name, "mode")) {
                        if (!strncasecmp(v->value, "di", 2)) 
                                mode = MODE_DIALTONE;
+                       else if (!strncasecmp(v->value, "sig", 3))
+                               mode = MODE_SIGMA;
                        else if (!strncasecmp(v->value, "im", 2))
                                mode = MODE_IMMEDIATE;
                        else if (!strncasecmp(v->value, "fxs", 3)) {
@@ -1370,9 +1398,11 @@ int load_module()
                        else
                                ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value);
                } else if (!strcasecmp(v->name, "context")) {
-                       strncpy(context, v->value, sizeof(context)-1);
+                       ast_copy_string(context, v->value, sizeof(context));
                } else if (!strcasecmp(v->name, "format")) {
-                       if (!strcasecmp(v->value, "g723.1")) {
+                       if (!strcasecmp(v->value, "g729")) {
+                               prefformat = AST_FORMAT_G729A;
+                        } else if (!strcasecmp(v->value, "g723.1")) {
                                prefformat = AST_FORMAT_G723_1;
                        } else if (!strcasecmp(v->value, "slinear")) {
                                if (mode == MODE_FXS)
@@ -1411,7 +1441,7 @@ int load_module()
        /* Make sure we can register our Adtranphone channel type */
 
        if (ast_channel_register(cur_tech)) {
-               ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
+               ast_log(LOG_ERROR, "Unable to register channel class 'Phone'\n");
                ast_config_destroy(cfg);
                __unload_module();
                return -1;
@@ -1422,17 +1452,4 @@ int load_module()
        return 0;
 }
 
-int usecount()
-{
-       return usecnt;
-}
-
-char *description()
-{
-       return (char *) desc;
-}
-
-char *key()
-{
-       return ASTERISK_GPL_KEY;
-}
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Linux Telephony API Support");