--- channels/chan_unicall.c.orig	2005-10-29 09:56:18.000000000 -0500
+++ channels/chan_unicall.c	2007-02-04 17:10:14.000000000 -0600
@@ -25,7 +25,7 @@
 #include <math.h>
 #include <ctype.h>
 #include <tiffio.h>
-#include <linux/zaptel.h>
+#include <zaptel/zaptel.h>
 
 #include <spandsp.h>
 #include <libsupertone.h>
@@ -157,31 +157,42 @@
 static int unicall_answer(struct ast_channel *c);
 static struct ast_frame *unicall_read(struct ast_channel *c);
 static int unicall_write(struct ast_channel *c, struct ast_frame *f);
-static int unicall_indicate(struct ast_channel *c, int condition);
+static int unicall_indicate(struct ast_channel *c, int condition, const void *data, size_t datalen);
 static int unicall_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
 static int unicall_digit(struct ast_channel *c, char digit);
 static int unicall_send_text(struct ast_channel *c, const char *text);
-static int unicall_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc);
+static int unicall_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeout);
 struct ast_frame *unicall_exception(struct ast_channel *ast);
 static int unicall_setoption(struct ast_channel *chan, int option, void *data, int datalen);
 
+/* TODO: implement missing interface methods */
 static const struct ast_channel_tech unicall_tech = {
     .type = type,
     .description = tdesc,
     .capabilities = AST_FORMAT_ULAW,
     .requester = unicall_request,
+    .devicestate = NULL, 
+    .send_digit_begin = unicall_digit,
+    .send_digit_end = NULL,
     .call = unicall_call,
     .hangup = unicall_hangup,
     .answer = unicall_answer,
     .read = unicall_read,
     .write = unicall_write,
-    .indicate = unicall_indicate,
-    .fixup = unicall_fixup,
-    .send_digit = unicall_digit,
     .send_text = unicall_send_text,
-    .bridge = unicall_bridge,
+    .send_image = NULL,
+    .send_html = NULL,
     .exception = unicall_exception,
+    .bridge = unicall_bridge,
+    .indicate = unicall_indicate,
+    .fixup = unicall_fixup,
     .setoption = unicall_setoption,
+    .queryoption = NULL,
+    .transfer  = NULL,
+    .write_video = NULL,
+    .bridged_channel = NULL,
+    .func_channel_read = NULL,
+    .func_channel_write = NULL
 };
 
 struct unicall_pvt;
@@ -345,27 +356,6 @@
 static int unicall_open(struct unicall_pvt *p, char *fn);
 static int unicall_close(int fd);
 
-/* Translate between Unicall causes and ast */
-static int hangup_uc2cause(int cause)
-{
-    switch (cause)
-    {
-    case UC_CAUSE_USER_BUSY:
-        return AST_CAUSE_BUSY;
-    case UC_CAUSE_NORMAL_CLEARING:
-        return AST_CAUSE_NORMAL;
-    case UC_CAUSE_NETWORK_CONGESTION:
-    case UC_CAUSE_REQ_CHANNEL_NOT_AVAILABLE:
-        return AST_CAUSE_CONGESTION;
-    case UC_CAUSE_UNASSIGNED_NUMBER:
-    case UC_CAUSE_NUMBER_CHANGED:
-        return AST_CAUSE_UNALLOCATED;
-    default:
-        return AST_CAUSE_FAILURE;
-    }
-    return 0;
-}
-
 /* translate between ast cause and Unicall */
 static int hangup_cause2uc(int cause)
 {
@@ -380,7 +370,7 @@
     return 0;
 }
 
-int select_codec(struct unicall_pvt *p, int index, int new_codec)
+static int select_codec(struct unicall_pvt *p, int index, int new_codec)
 {
     int res;
 
@@ -549,8 +539,8 @@
     {
         buf[0] = digit;
         buf[1] = '\0';
-ast_log(LOG_WARNING, "Sending DTMF digit\n");
-        dtmf_put(&p->subs[SUB_REAL].dtmf_tx_state, buf);
+		ast_log(LOG_DEBUG, "Sending DTMF digit\n");
+        dtmf_tx_put(&p->subs[SUB_REAL].dtmf_tx_state, buf);
         p->dialing = TRUE;
     }
     /*endif*/    
@@ -791,19 +781,6 @@
     return useslavenative;
 }
 
-static int reset_conf(struct unicall_pvt *p)
-{
-    p->confno = -1;
-    if (p->subs[SUB_REAL].fd > -1)
-    {
-        if (uc_channel_switching(p->uc, 0, UC_SWITCHING_FREE, 0, 0) != UC_RET_OK)
-            ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d!\n", p->channel);
-        /*endif*/
-    }
-    /*endif*/
-    return 0;
-}
-
 static int update_conf(struct unicall_pvt *p)
 {
     int needconf;
@@ -922,26 +899,6 @@
     /*endif*/
 }
 
-static void unicall_train_ec(struct unicall_pvt *p)
-{
-    int x;
-
-    if (p  &&  p->echocancel  &&  p->echotraining)
-    {
-        x = (p->echotraining)  ?  UC_ECHO_CANCEL_TRAINING  :  UC_ECHO_CANCEL_NOTRAINING;
-        if (uc_channel_echo_cancel(p->uc, 0, x) != UC_RET_OK)
-            ast_log(LOG_WARNING, "Unable to request echo training on channel %d\n", p->channel);
-        else
-            ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
-        /*endif*/
-    }
-    else
-    {
-        ast_log(LOG_DEBUG, "No echo training requested\n");
-    }
-    /*endif*/
-}
-
 static void unicall_disable_ec(struct unicall_pvt *p)
 {
     if (p == NULL)
@@ -1277,10 +1234,11 @@
             /* Ditch the holding callwait call, and immediately make it availabe */
             if (p->subs[SUB_CALLWAIT].inthreeway)
             {
+				struct ast_channel *bridged_chan = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
                 /* This is actually part of a three way, placed on hold.  Place the third part
                    on music on hold now */
-                if (p->subs[SUB_THREEWAY].owner  &&  ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
-                    ast_moh_start(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), NULL);
+                if (p->subs[SUB_THREEWAY].owner  &&  bridged_chan )
+                    ast_moh_start(bridged_chan, bridged_chan->musicclass, NULL);
                 /*endif*/
                 p->subs[SUB_THREEWAY].inthreeway = FALSE;
                 /* Make it the call wait now */
@@ -1296,10 +1254,11 @@
         case SUB_THREEWAY:
             if (p->subs[SUB_CALLWAIT].inthreeway)
             {
+				struct ast_channel *bridged_chan = ast_bridged_channel(p->subs[SUB_CALLWAIT].owner);
                 /* The other party of the three way call is currently in a call-wait state.
                    Start music on hold for them, and take the main guy out of the third call */
-                if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner))
-                    ast_moh_start(ast_bridged_channel(p->subs[SUB_CALLWAIT].owner), NULL);
+                if (p->subs[SUB_CALLWAIT].owner && bridged_chan )
+                    ast_moh_start(bridged_chan, bridged_chan->musicclass, NULL);
                 /*endif*/
                 p->subs[SUB_CALLWAIT].inthreeway = FALSE;
             }
@@ -1408,7 +1367,7 @@
     /*endif*/
     if (p->crn)
     {
-        ast_log(LOG_WARNING, "Answer Call\n");
+        ast_log(LOG_DEBUG, "Answer Call\n");
         if ((ret = uc_call_control(p->uc, UC_OP_ANSWERCALL, p->crn, NULL)))
             ast_log(LOG_WARNING, "Answer call failed on %s - %s\n", ast->name, uc_ret2str(ret));
         /*endif*/
@@ -1427,7 +1386,7 @@
     char *cp;
     int x;
 
-    ast_log(LOG_WARNING, "unicall_setoption called - %d\n", option);
+    ast_log(LOG_DEBUG, "unicall_setoption called - %d\n", option);
     if (option != AST_OPTION_TONE_VERIFY
         &&
         option != AST_OPTION_TDD
@@ -1584,7 +1543,7 @@
     ast_log(LOG_DEBUG, "Making %d slave to master %d\n", slave->channel, master->channel);
 }
 
-static int unicall_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc)
+static enum ast_bridge_result unicall_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timoutms)
 {
     struct unicall_pvt *p0;
     struct unicall_pvt *p1;
@@ -1617,16 +1576,16 @@
     os2 = -1;
     inconf = FALSE;
     nothingok = FALSE;
-    ast_log(LOG_WARNING, "unicall_bridge called\n");
+    ast_log(LOG_DEBUG, "unicall_bridge called\n");
     /* If need DTMF, can't native bridge */
     if ((flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)))
-        return -2;
+        return AST_BRIDGE_FAILED_NOWARN;
     /*endif*/
     p0 = c0->tech_pvt;
     p1 = c1->tech_pvt;
     /* Can't do pseudo-channels here */
     if (p0->protocol_class == NULL  ||  p1->protocol_class == NULL)
-        return -2;
+        return AST_BRIDGE_FAILED_NOWARN;
     /*endif*/
     ast_mutex_lock(&c0->lock);
     ast_mutex_lock(&c1->lock);
@@ -1641,7 +1600,7 @@
     oc1 = p0->owner;
     oc2 = p1->owner;
     if (oi1 < 0  ||  oi2 < 0)
-        return -1;
+        return AST_BRIDGE_FAILED;
     /*endif*/
     ast_mutex_lock(&p0->lock);
     if (ast_mutex_trylock(&p1->lock))
@@ -1651,7 +1610,7 @@
         ast_mutex_unlock(&c0->lock);
         ast_mutex_unlock(&c1->lock);
         ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
-        return -3;
+        return AST_BRIDGE_RETRY;
     }
     /*endif*/
     if (oi1 == SUB_REAL  &&  oi2 == SUB_REAL)
@@ -1817,7 +1776,7 @@
 
     /* Native bridge failed */
     if ((master == NULL  ||  slave == NULL)  &&  !nothingok)
-        return -1;
+        return AST_BRIDGE_FAILED;
     /*endif*/
     cs[SUB_REAL] = c0;
     cs[SUB_CALLWAIT] = c1;
@@ -1871,7 +1830,7 @@
                     oi1,
                     op1->channel,
                     oi2);
-            return -3;
+            return AST_BRIDGE_RETRY;
         }
         /*endif*/
         to = -1;
@@ -1899,7 +1858,7 @@
             if (slave  &&  master)
                 unicall_unlink(slave, master);
             /*endif*/
-            return 0;
+            return AST_BRIDGE_COMPLETE;
         }
         /*endif*/
         if (f->frametype == AST_FRAME_DTMF)
@@ -1913,7 +1872,7 @@
                 if (slave  &&  master)
                     unicall_unlink(slave, master);
                 /*endif*/
-                return 0;
+                return AST_BRIDGE_COMPLETE;
             }
             /*endif*/
         }
@@ -1928,7 +1887,7 @@
     /*endif*/
 }
 
-static int unicall_indicate(struct ast_channel *chan, int condition);
+static int unicall_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
 
 static int unicall_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
 {
@@ -1937,7 +1896,7 @@
 
     p = newchan->tech_pvt;
     ast_mutex_lock(&p->lock);
-    ast_log(LOG_WARNING, "New owner for channel %d is %s\n", p->channel, newchan->name);
+    ast_log(LOG_NOTICE, "New owner for channel %d is %s\n", p->channel, newchan->name);
     //ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
     if (p->owner == oldchan)
         p->owner = newchan;
@@ -1955,7 +1914,7 @@
     }
     /*endfor*/
     if (newchan->_state == AST_STATE_RINGING) 
-        unicall_indicate(newchan, AST_CONTROL_RINGING);
+        unicall_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
     /*endif*/
     update_conf(p);
     ast_mutex_unlock(&p->lock);
@@ -1997,7 +1956,7 @@
     }
     /*endif*/
     if (!p->radio)
-        ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
+        ast_log(LOG_NOTICE, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
     /*endif*/
     /* If it's not us, return NULL immediately */
     if (ast != p->owner)
@@ -2011,7 +1970,7 @@
     return &p->subs[index].f;
 }
 
-void handle_uc_read(uc_t *uc, int ch, void *user_data, uint8_t *buf, int len)
+static void handle_uc_read(uc_t *uc, int ch, void *user_data, uint8_t *buf, int len)
 {
     void *readbuf;
     struct unicall_pvt *p;
@@ -2148,7 +2107,7 @@
     /* Check first for any outstanding DTMF characters */
     if (p->subs[index].dtmfq[0])
     {
-        ast_log(LOG_WARNING, "got a DTMF %d\n", p->subs[index].dtmfq[0]);
+        ast_log(LOG_NOTICE, "got a DTMF %d\n", p->subs[index].dtmfq[0]);
         p->subs[index].f.subclass = p->subs[index].dtmfq[0];
         memmove(&p->subs[index].dtmfq[0], &p->subs[index].dtmfq[1], sizeof(p->subs[index].dtmfq) - 1);
         p->subs[index].f.frametype = AST_FRAME_DTMF;
@@ -2203,7 +2162,7 @@
         /*endif*/
         if (p->confirmanswer)
         {
-            ast_log(LOG_WARNING, "Confirm answer!\n");
+            ast_log(LOG_NOTICE, "Confirm answer!\n");
             /* Upon receiving a DTMF digit, consider this an answer confirmation instead
                of a DTMF digit */
             p->subs[index].f.frametype = AST_FRAME_CONTROL;
@@ -2430,7 +2389,8 @@
     return 0;
 }
 
-static int unicall_indicate(struct ast_channel *chan, int condition)
+/* TODO: proper *data management */
+static int unicall_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
 {
     struct unicall_pvt *p;
     int res = -1;
@@ -2438,7 +2398,7 @@
     int ret;
 
     p = chan->tech_pvt;
-    ast_log(LOG_WARNING, "unicall_indicate %d\n", condition);
+    ast_log(LOG_NOTICE, "unicall_indicate %d\n", condition);
     if ((index = unicall_get_index(chan, p, 0)) != SUB_REAL)
         return 0;
     /*endif*/
@@ -2496,15 +2456,11 @@
 static struct ast_channel *unicall_new(struct unicall_pvt *i, int state, int startpbx, int index, int law)
 {
     struct ast_channel *tmp;
+	char chan_name[AST_CHANNEL_NAME];
     int deflaw;
     int x;
     int y;
 
-    if ((tmp = ast_channel_alloc(0)) == NULL)
-    {
-        ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
-        return  NULL;
-    }
     /*endif*/
     if (law == 0)
         law = uc_channel_get_api_codec(i->uc, 0);
@@ -2517,10 +2473,10 @@
     y = 1;
     do
     {
-        snprintf(tmp->name, sizeof(tmp->name), "UniCall/%d-%d", i->channel, y);
+        snprintf(chan_name, sizeof(chan_name), "UniCall/%d-%d", i->channel, y);
         for (x = 0;  x < 3;  x++)
         {
-            if (index != x  &&  i->subs[x].owner  &&  strcasecmp(tmp->name, i->subs[x].owner->name) == 0)
+            if (index != x && i->subs[x].owner && strcasecmp(chan_name, i->subs[x].owner->name) == 0)
                 break;
             /*endif*/
         }
@@ -2528,7 +2484,13 @@
         y++;
     }
     while (x < 3);
-    tmp->type = type;
+
+    if ( ( tmp = ast_channel_alloc(0, state, 0, 0, chan_name) ) == NULL)
+    {
+        ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
+        return  NULL;
+    }
+
     tmp->tech = &unicall_tech;
     tmp->fds[0] = i->subs[index].fd;
     tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
@@ -2562,16 +2524,16 @@
     /*endif*/
     tmp->tech_pvt = i;
     if (strlen(i->language))
-        strncpy(tmp->language, i->language, sizeof(tmp->language) - 1);
+        ast_string_field_set(tmp, language, i->language);
     /*endif*/
     if (strlen(i->musicclass))
-        strncpy(tmp->musicclass, i->musicclass, sizeof(tmp->musicclass) - 1);
+        ast_string_field_set(tmp, musicclass, i->musicclass);
     /*endif*/
     if (i->owner == NULL)
         i->owner = tmp;
     /*endif*/
     if (strlen(i->accountcode))
-        strncpy(tmp->accountcode, i->accountcode, sizeof(tmp->accountcode) - 1);
+        ast_string_field_set(tmp, accountcode, i->accountcode);
     /*endif*/
     if (i->amaflags)
         tmp->amaflags = i->amaflags;
@@ -2580,14 +2542,13 @@
         ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
     /*endif*/
     i->subs[index].owner = tmp;
-    ast_setstate(tmp, state);
     ast_mutex_lock(&usecnt_lock);
     usecnt++;
     ast_mutex_unlock(&usecnt_lock);
     ast_update_use_count();
     strncpy(tmp->context, i->context, sizeof(tmp->context) - 1);
     /* Copy call forward info */
-    strncpy(tmp->call_forward, i->call_forward, sizeof(tmp->call_forward));
+    ast_string_field_set(tmp, call_forward, i->call_forward);
     /* If we've been told "no ADSI" then enforce it */
     if (!i->adsi)
         tmp->adsicpe = AST_ADSI_UNAVAILABLE;
@@ -2621,13 +2582,7 @@
     return tmp;
 }
 
-int channel_error(uc_t *uc, int user_data, int cause)
-{
-    ast_log(LOG_ERROR, "Channel error - %d\n", cause);
-    return  0;
-}
-
-void handle_uc_event(uc_t *uc, void *user_data, uc_event_t *ev)
+static void handle_uc_event(uc_t *uc, void *user_data, uc_event_t *ev)
 {
     struct ast_channel *c;
     struct unicall_pvt *i;
@@ -2641,12 +2596,11 @@
     /*endif*/
     /* Handle an event on a given channel for the monitor thread. */
 
-    ast_log(LOG_WARNING, "Unicall/%d event %s\n", i->channel, uc_event2str(ev->e));
+    ast_log(LOG_NOTICE, "Unicall/%d event %s\n", i->channel, uc_event2str(ev->e));
     switch (ev->e)
     {
     case UC_EVENT_PROTOCOLFAIL:
-        if (option_verbose > 2)
-            ast_verbose(VERBOSE_PREFIX_3 "Unicall/%d protocol error. Cause %d\n", i->channel, ev->gen.data);
+         ast_log(LOG_ERROR, "Unicall/%d protocol error. Cause %d\n", i->channel, ev->gen.data);
         /*endif*/
         if (!i->blocked)
         {
@@ -2696,7 +2650,7 @@
         break;
     case UC_EVENT_OFFERED:
         /* Check for callerid, digits, etc */
-        ast_log(LOG_WARNING,
+        ast_log(LOG_NOTICE,
                 "CRN %d - Offered on channel %d (ANI: %s, DNIS: %s, Cat: %d)\n",
                 ev->offered.crn,
                 ev->offered.channel,
@@ -2783,7 +2737,7 @@
         /*endif*/
         break;
     case UC_EVENT_MOREDIGITS:
-        ast_log(LOG_WARNING, "Dest '%s'\n", ev->offered.parms.destination_number);
+        ast_log(LOG_NOTICE, "Dest '%s'\n", ev->offered.parms.destination_number);
         if ((ch = ev->offered.channel) >= 0)
         {
             /* Get caller ID */
@@ -2897,7 +2851,7 @@
             else
             {
                 i->dialing = TRUE;
-                dtmf_put(&i->subs[SUB_REAL].dtmf_tx_state, i->dialstr);
+                dtmf_tx_put(&i->subs[SUB_REAL].dtmf_tx_state, i->dialstr);
                 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", i->dialstr);
                 i->dialstr[0] = '\0';
             }
@@ -2927,7 +2881,7 @@
     case UC_EVENT_FARDISCONNECTED:
         if ((ch = ev->fardisconnected.channel) >= 0)
         {
-            ast_log(LOG_WARNING, "CRN %d - far disconnected cause=%s [%d]\n", ev->fardisconnected.crn, uc_cause2str(ev->fardisconnected.cause), ev->fardisconnected.cause);
+            ast_log(LOG_NOTICE, "CRN %d - far disconnected cause=%s [%d]\n", ev->fardisconnected.crn, uc_cause2str(ev->fardisconnected.cause), ev->fardisconnected.cause);
             if (i->owner)
             {
                 i->alreadyhungup = TRUE;
@@ -3717,7 +3671,7 @@
     return group;
 }
 
-static char *complete_span(char *line, char *word, int pos, int state)
+static char *complete_span(const char *line, const char *word, int pos, int state)
 {
     int span;
     char tmp[50];
@@ -3814,11 +3768,11 @@
     return RESULT_SUCCESS;
 }
 
-static char uc_debug_help[] = 
+static const char uc_debug_help[] = 
     "Usage: UC debug span <span>\n"
     "       Enables debugging on a given PRI span\n";
     
-static char uc_no_debug_help[] = 
+static const char uc_no_debug_help[] = 
     "Usage: UC no debug span <span>\n"
     "       Disables debugging on a given PRI span\n";
 
@@ -3988,6 +3942,8 @@
     {"UC", "destroy", "channel", NULL}, unicall_destroy_channel, "Destroy a channel", destroy_channel_usage, NULL
 };
 
+static int unload_module(void);
+
 static int setup_unicall(int reload)
 {
     struct unicall_pvt *tmp;
@@ -4271,7 +4227,7 @@
     return 0;
 }
 
-int load_module(void)
+static int load_module(void)
 {
     uc_start();
     uc_set_error_handler(unicall_report);
@@ -4293,7 +4249,7 @@
     return 0;
 }
 
-int unload_module(void)
+static int unload_module(void)
 {
     struct unicall_pvt *p;
     struct unicall_pvt *pl;
@@ -4386,7 +4342,7 @@
     return  0;
 }
 
-int reload(void)
+static int reload(void)
 {
     int res;
 
@@ -4398,22 +4354,14 @@
     return 0;
 }
 
-int usecount(void)
-{
-    int res;
+/* This is a workaround so that menuselect displays a proper description
+ * AST_MODULE_INFO(, , "Unicall / R2"
+ */
 
-    ast_mutex_lock(&usecnt_lock);
-    res = usecnt;
-    ast_mutex_unlock(&usecnt_lock);
-    return res;
-}
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
+		.load = load_module,
+		.unload = unload_module,
+		.reload = reload,
+);
 
-char *description(void)
-{
-    return (char *) desc;
-}
 
-char *key(void)
-{
-    return ASTERISK_GPL_KEY;
-}

