Version 0.1.10 from FTP
authorMark Spencer <markster@digium.com>
Thu, 20 Dec 2001 15:21:47 +0000 (15:21 +0000)
committerMark Spencer <markster@digium.com>
Thu, 20 Dec 2001 15:21:47 +0000 (15:21 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@395 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_dial.c
apps/app_echo.c
callerid.c
channel.c
configs/adsi.conf.sample [new file with mode: 0755]
configs/zapata.conf.sample
include/asterisk/adsi.h [new file with mode: 0755]
include/asterisk/callerid.h
include/asterisk/channel.h

index ee3e5e3..5b24c6f 100755 (executable)
@@ -19,6 +19,7 @@
 #include <asterisk/module.h>
 #include <asterisk/translate.h>
 #include <asterisk/say.h>
+#include <asterisk/parking.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <unistd.h>
 
 #include <pthread.h>
 
-static char *tdesc = "Dialing/Parking Application";
+static char *tdesc = "Dialing Application";
 
 static char *app = "Dial";
 
-static char *parkedcall = "ParkedCall";
-
 static char *synopsis = "Place an call and connect to the current channel";
 
-static char *registrar = "app_dial";
-
 static char *descrip =
 "  Dial(Technology/resource[&Technology2/resource2...][|timeout][|transfer]):\n"
 "Requests  one  or more channels and places specified outgoing calls on them.\n"
@@ -62,21 +59,6 @@ static char *descrip =
 "  In addition to transferring the call, a call may be parked and then picked\n"
 "up by another user.\n";
 
-/* No more than 45 seconds parked before you do something with them */
-static int parkingtime = 45000;
-
-/* Context for which parking is made accessible */
-static char parking_con[AST_MAX_EXTENSION] = "parkedcalls";
-
-/* Extension you type to park the call */
-static char parking_ext[AST_MAX_EXTENSION] = "700";
-
-/* First available extension for parking */
-static int parking_start = 701;
-
-/* Last available extension for parking */
-static int parking_stop = 750;
-
 /* We define a customer "local user" structure because we
    use it not only for keeping track of what is in use but
    also for keeping track of who we're dialing. */
@@ -88,174 +70,8 @@ struct localuser {
        struct localuser *next;
 };
 
-struct parkeduser {
-       struct ast_channel *chan;
-       struct timeval start;
-       int parkingnum;
-       /* Where to go if our parking time expires */
-       char context[AST_MAX_EXTENSION];
-       char exten[AST_MAX_EXTENSION];
-       int priority;
-       struct parkeduser *next;
-};
-
-static struct parkeduser *parkinglot;
-
-static pthread_mutex_t parking_lock = PTHREAD_MUTEX_INITIALIZER;
-
-static pthread_t parking_thread;
-
 LOCAL_USER_DECL;
 
-static int bridge_call(struct ast_channel *chan, struct ast_channel *peer, int allowredirect);
-
-
-static int park_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 parkeduser *pu, *cur;
-       int x;
-       pu = malloc(sizeof(struct parkeduser));
-       if (pu) {
-               ast_pthread_mutex_lock(&parking_lock);
-               for (x=parking_start;x<=parking_stop;x++) {
-                       cur = parkinglot;
-                       while(cur) {
-                               if (cur->parkingnum == x) 
-                                       break;
-                               cur = cur->next;
-                       }
-                       if (!cur)
-                               break;
-               }
-               if (x <= parking_stop) {
-                       pu->chan = chan;
-                       gettimeofday(&pu->start, NULL);
-                       pu->parkingnum = x;
-                       /* Remember what had been dialed, so that if the parking
-                          expires, we try to come back to the same place */
-                       strncpy(pu->context, chan->context, sizeof(pu->context));
-                       strncpy(pu->exten, chan->exten, sizeof(pu->exten));
-                       pu->priority = chan->priority;
-                       pu->next = parkinglot;
-                       parkinglot = pu;
-                       ast_pthread_mutex_unlock(&parking_lock);
-                       /* Wake up the (presumably select()ing) thread */
-                       pthread_kill(parking_thread, SIGURG);
-                       if (option_verbose > 1) 
-                               ast_verbose(VERBOSE_PREFIX_2 "Parked %s on %d\n", pu->chan->name, pu->parkingnum);
-                       ast_say_digits(peer, pu->parkingnum, peer->language);
-                       return 0;
-               } else {
-                       ast_log(LOG_WARNING, "No more parking spaces\n");
-                       free(pu);
-                       ast_pthread_mutex_unlock(&parking_lock);
-                       return -1;
-               }
-       } else {
-               ast_log(LOG_WARNING, "Out of memory\n");
-               return -1;
-       }
-       return 0;
-}
-
-static void *do_parking_thread(void *ignore)
-{
-       int ms, tms, max;
-       struct parkeduser *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_pthread_mutex_lock(&parking_lock);
-               pl = NULL;
-               pu = parkinglot;
-               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;
-                       if (tms > parkingtime) {
-                               /* They've been waiting too long, send them back to where they came.  Theoretically they
-                                  should have their original extensions and such, but we copy to be on the safe side */
-                               strncpy(pu->chan->exten, pu->exten, sizeof(pu->chan->exten));
-                               strncpy(pu->chan->context, pu->context, sizeof(pu->chan->context));
-                               pu->chan->priority = pu->priority;
-                               /* Start up the PBX, or hang them up */
-                               if (ast_pbx_start(pu->chan))  {
-                                       ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
-                                       ast_hangup(pu->chan);
-                               }
-                               /* And take them out of the parking lot */
-                               if (pl) 
-                                       pl->next = pu->next;
-                               else
-                                       parkinglot = pu->next;
-                               pt = pu;
-                               pu = pu->next;
-                               free(pt);
-                       } else {
-                               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))
-                                                               pu->chan->exception = 1;
-                                                       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 parked\n", pu->chan->name);
-                                                       ast_hangup(pu->chan);
-                                                       /* And take them out of the parking lot */
-                                                       if (pl) 
-                                                               pl->next = pu->next;
-                                                       else
-                                                               parkinglot = 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) {
-                                       /* Keep this one for next one */
-std:                           FD_SET(pu->chan->fds[x], &nrfds);
-                                       FD_SET(pu->chan->fds[x], &nefds);
-                                       /* Keep track of our longest wait */
-                                       if ((tms < ms) || (ms < 0))
-                                               ms = tms;
-                                       if (pu->chan->fds[x] > max)
-                                               max = pu->chan->fds[x];
-                                       pl = pu;
-                                       pu = pu->next;
-                               }
-                       }
-               }
-               ast_pthread_mutex_unlock(&parking_lock);
-               rfds = nrfds;
-               efds = nefds;
-               tv.tv_sec = ms / 1000;
-               tv.tv_usec = (ms % 1000) * 1000;
-               /* Wait for something to happen */
-               select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
-               pthread_testcancel();
-       }
-       return NULL;    /* Never reached */
-}
-
 static void hanguptree(struct localuser *outgoing, struct ast_channel *exception)
 {
        /* Hang up a tree of stuff */
@@ -344,12 +160,16 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
                                                        if (option_verbose > 2)
                                                                ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name);
                                                        o->stillgoing = 0;
+                                                       if (in->cdr)
+                                                               ast_cdr_busy(in->cdr);
                                                        numbusies++;
                                                        break;
                                                case AST_CONTROL_CONGESTION:
                                                        if (option_verbose > 2)
                                                                ast_verbose( VERBOSE_PREFIX_3 "%s is circuit-busy\n", o->chan->name);
                                                        o->stillgoing = 0;
+                                                       if (in->cdr)
+                                                               ast_cdr_busy(in->cdr);
                                                        numbusies++;
                                                        break;
                                                case AST_CONTROL_RINGING:
@@ -401,177 +221,6 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
        
 }
 
-static int bridge_call(struct ast_channel *chan, struct ast_channel *peer, int allowredirect)
-{
-       /* Copy voice back and forth between the two channels.  Give the peer
-          the ability to transfer calls with '#<extension' syntax. */
-       int len;
-       struct ast_frame *f;
-       struct ast_channel *who;
-       char newext[256], *ptr;
-       int res;
-       struct ast_option_header *aoh;
-       /* Answer if need be */
-       if (chan->state != AST_STATE_UP) {
-               if (ast_answer(chan))
-                       return -1;
-       }
-       peer->appl = "Bridged Call";
-       peer->data = chan->name;
-       for (;;) {
-               res = ast_channel_bridge(chan, peer, allowredirect ? AST_BRIDGE_DTMF_CHANNEL_1 : 0, &f, &who);
-               if (res < 0) {
-                       ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
-                       return -1;
-               }
-               
-               if (!f || ((f->frametype == AST_FRAME_CONTROL) && ((f->subclass == AST_CONTROL_HANGUP) || (f->subclass == AST_CONTROL_BUSY) || 
-                       (f->subclass == AST_CONTROL_CONGESTION)))) {
-                               res = -1;
-                               break;
-               }
-               if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RINGING)) {
-                       if (who == chan)
-                               ast_indicate(peer, AST_CONTROL_RINGING);
-                       else
-                               ast_indicate(chan, AST_CONTROL_RINGING);
-               }
-               if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_OPTION)) {
-                       aoh = f->data;
-                       /* Forward option Requests */
-                       if (aoh && (aoh->flag == AST_OPTION_FLAG_REQUEST)) {
-                               if (who == chan)
-                                       ast_channel_setoption(peer, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0);
-                               else
-                                       ast_channel_setoption(chan, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0);
-                       }
-               }
-               if ((f->frametype == AST_FRAME_DTMF) && (who == peer) && allowredirect &&
-                    (f->subclass == '#')) {
-                               memset(newext, 0, sizeof(newext));
-                               ptr = newext;
-                                       /* Transfer */
-                               if ((res=ast_streamfile(peer, "pbx-transfer", chan->language)))
-                                       break;
-                               if ((res=ast_waitstream(peer, AST_DIGIT_ANY)) < 0)
-                                       break;
-                               ast_stopstream(peer);
-                               if (res > 0) {
-                                       /* If they've typed a digit already, handle it */
-                                       newext[0] = res;
-                                       ptr++;
-                                       len --;
-                               }
-                               res = 0;
-                               while(strlen(newext) < sizeof(newext - 1)) {
-                                       res = ast_waitfordigit(peer, 3000);
-                                       if (res < 1)
-                                               break;
-                                       *(ptr++) = res;
-                                       if (!ast_canmatch_extension(peer, peer->context, newext, 1, peer->callerid) ||
-                                               ast_exists_extension(peer, peer->context, newext, 1, peer->callerid)) {
-                                               res = 0;
-                                               break;
-                                       }
-                               }
-                               if (res)
-                                       break;
-                               if (!strcmp(newext, parking_ext)) {
-                                       if (!park_call(chan, peer)) {
-                                               /* We return non-zero, but tell the PBX not to hang the channel when
-                                                  the thread dies -- We have to be careful now though.  We are responsible for 
-                                                  hanging up the channel, else it will never be hung up! */
-                                               res=AST_PBX_KEEPALIVE;
-                                               break;
-                                       } else {
-                                               ast_log(LOG_WARNING, "Unable to park call %s\n", chan->name);
-                                       }
-                                       /* XXX Maybe we should have another message here instead of invalid extension XXX */
-                               } else if (ast_exists_extension(chan, peer->context, newext, 1, peer->callerid)) {
-                                       /* Set the channel's new extension, since it exists, using peer context */
-                                       strncpy(chan->exten, newext, sizeof(chan->exten));
-                                       strncpy(chan->context, peer->context, sizeof(chan->context));
-                                       chan->priority = 0;
-                                       ast_frfree(f);
-                                       if (option_verbose > 2) 
-                                               ast_verbose(VERBOSE_PREFIX_3 "Transferring %s to '%s' (context %s) priority 1\n", chan->name, chan->exten, chan->context);
-                                       res=0;
-                                       break;
-                               } else {
-                                       if (option_verbose > 2) 
-                                               ast_verbose(VERBOSE_PREFIX_3 "Unable to find extension '%s' in context %s\n", newext, peer->context);
-                               }
-                               res = ast_streamfile(peer, "pbx-invalid", chan->language);
-                               if (res)
-                                       break;
-                               res = ast_waitstream(peer, AST_DIGIT_ANY);
-                               ast_stopstream(peer);
-                               res = 0;
-                       } else {
-#if 1
-                               ast_log(LOG_DEBUG, "Read from %s (%d,%d)\n", who->name, f->frametype, f->subclass);
-#endif
-                       }
-       }
-       return res;
-}
-
-static int park_exec(struct ast_channel *chan, void *data)
-{
-       int res=0;
-       struct localuser *u;
-       struct ast_channel *peer=NULL;
-       struct parkeduser *pu, *pl=NULL;
-       int park;
-       if (!data) {
-               ast_log(LOG_WARNING, "Park requires an argument (extension number)\n");
-               return -1;
-       }
-       LOCAL_USER_ADD(u);
-       park = atoi((char *)data);
-       ast_pthread_mutex_lock(&parking_lock);
-       pu = parkinglot;
-       while(pu) {
-               if (pu->parkingnum == park) {
-                       if (pl)
-                               pl->next = pu->next;
-                       else
-                               parkinglot = pu->next;
-                       break;
-               }
-               pu = pu->next;
-       }
-       ast_pthread_mutex_unlock(&parking_lock);
-       if (pu) {
-               peer = pu->chan;
-               free(pu);
-       }
-       if (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 parked call %d\n", chan->name, park);
-               res = bridge_call(peer, chan, 1);
-               /* Simulate the PBX hanging up */
-               if (res != AST_PBX_KEEPALIVE)
-                       ast_hangup(peer);
-               return -1;
-       } else {
-               /* XXX Play a message XXX */
-               if (option_verbose > 2) 
-                       ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to non-existant parked call %d\n", chan->name, park);
-               res = -1;
-       }
-       LOCAL_USER_REMOVE(u);
-       return res;
-}
-
 static int dial_exec(struct ast_channel *chan, void *data)
 {
        int res=-1;
@@ -599,7 +248,7 @@ static int dial_exec(struct ast_channel *chan, void *data)
                ast_log(LOG_WARNING, "Out of memory\n");
                return -1;
        }
-       strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION);
+       strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION-1);
        peers = info;
        if (peers) {
                timeout = strchr(info, '|');
@@ -645,10 +294,10 @@ static int dial_exec(struct ast_channel *chan, void *data)
                        tmp->allowredirect = 1;
                else
                        tmp->allowredirect = 0;
-               strncpy(numsubst, number, sizeof(numsubst));
+               strncpy(numsubst, number, sizeof(numsubst)-1);
                /* If we're dialing by extension, look at the extension to know what to dial */
                if ((newnum = strstr(numsubst, "BYEXTENSION"))) {
-                       strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit));
+                       strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit)-1);
                        snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s%s", chan->exten,restofit);
                        if (option_debug)
                                ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
@@ -657,19 +306,24 @@ static int dial_exec(struct ast_channel *chan, void *data)
                tmp->chan = ast_request(tech, chan->nativeformats, numsubst);
                if (!tmp->chan) {
                        /* If we can't, just go on to the next call */
-                       ast_log(LOG_WARNING, "Unable to create channel of type '%s'\n", tech);
+                       ast_log(LOG_NOTICE, "Unable to create channel of type '%s'\n", tech);
+                       if (chan->cdr)
+                               ast_cdr_busy(chan->cdr);
                        free(tmp);
                        cur = rest;
                        continue;
                }
                tmp->chan->appl = "AppDial";
                tmp->chan->data = "(Outgoing Line)";
+               tmp->chan->whentohangup = 0;
                if (tmp->chan->callerid)
                        free(tmp->chan->callerid);
                if (chan->callerid)
                        tmp->chan->callerid = strdup(chan->callerid);
                else
                        tmp->chan->callerid = NULL;
+               /* Presense of ADSI CPE on outgoing channel follows ours */
+               tmp->chan->adsicpe = chan->adsicpe;
                /* Place the call, but don't wait on the answer */
                res = ast_call(tmp->chan, numsubst, 0);
                if (res) {
@@ -715,6 +369,9 @@ static int dial_exec(struct ast_channel *chan, void *data)
                   conversation.  */
                hanguptree(outgoing, peer);
                outgoing = NULL;
+               /* If appropriate, log that we have a destination channel */
+               if (chan->cdr)
+                       ast_cdr_setdestchan(chan->cdr, peer->name);
                /* Make sure channels are compatible */
                res = ast_channel_make_compatible(chan, peer);
                if (res < 0) {
@@ -730,7 +387,7 @@ static int dial_exec(struct ast_channel *chan, void *data)
                        int x = 2;
                        ast_channel_setoption(peer,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
                }                       
-               res = bridge_call(chan, peer, allowredir);
+               res = ast_bridge_call(chan, peer, allowredir);
                ast_hangup(peer);
        }       
 out:
@@ -749,25 +406,7 @@ int unload_module(void)
 int load_module(void)
 {
        int res;
-       int x;
-       struct ast_context *con;
-       char exten[AST_MAX_EXTENSION];
-       con = ast_context_find(parking_con);
-       if (!con) {
-               con = ast_context_create(parking_con, registrar);
-               if (!con) {
-                       ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
-                       return -1;
-               }
-       }
-       for(x=parking_start; x<=parking_stop;x++) {
-               snprintf(exten, sizeof(exten), "%d", x);
-               ast_add_extension2(con, 1, exten, 1, NULL, parkedcall, strdup(exten), free, registrar);
-       }
-       pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
-       res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
-       if (!res)
-               res = ast_register_application(app, dial_exec, synopsis, descrip);
+       res = ast_register_application(app, dial_exec, synopsis, descrip);
        return res;
 }
 
index 669018e..cacfe07 100755 (executable)
@@ -44,6 +44,8 @@ static int echo_exec(struct ast_channel *chan, void *data)
        struct localuser *u;
        struct ast_frame *f;
        LOCAL_USER_ADD(u);
+       ast_set_write_format(chan, ast_best_codec(chan->nativeformats));
+       ast_set_read_format(chan, ast_best_codec(chan->nativeformats));
        /* Do our thing here */
        while((f = ast_read(chan))) {
                if (f->frametype == AST_FRAME_VOICE) {
index 438d2b3..a3d9f42 100755 (executable)
@@ -43,8 +43,8 @@ struct callerid_state {
        int len;
 };
 
-static float dr[4], di[4];
-static float clidsb = 8000.0 / 1200.0;
+float dr[4], di[4];
+float clidsb = 8000.0 / 1200.0;
 
 #define CALLERID_SPACE 2200.0          /* 2200 hz for "0" */
 #define CALLERID_MARK  1200.0          /* 1200 hz for "1" */
@@ -98,21 +98,23 @@ void callerid_get(struct callerid_state *cid, char **name, char **number, int *f
                *number = cid->number;
 }
 
-int ast_callerid_gen_cas(unsigned char *outbuf, int len)
+int ast_gen_cas(unsigned char *outbuf, int sendsas, int len)
 {
        int pos = 0;
        int cnt;
        int saslen=2400;
-       if (len < saslen)
-               return -1;
-       while(saslen) {
-               cnt = saslen;
-               if (cnt > sizeof(sas))
-                       cnt = sizeof(sas);
-               memcpy(outbuf + pos, sas, cnt);
-               pos += cnt;
-               len -= cnt;
-               saslen -= cnt;
+       if (sendsas) {
+               if (len < saslen)
+                       return -1;
+               while(saslen) {
+                       cnt = saslen;
+                       if (cnt > sizeof(sas))
+                               cnt = sizeof(sas);
+                       memcpy(outbuf + pos, sas, cnt);
+                       pos += cnt;
+                       len -= cnt;
+                       saslen -= cnt;
+               }
        }
        while(len) {
                cnt = len;
@@ -142,7 +144,7 @@ int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len)
        memcpy(buf, cid->oldstuff, cid->oldlen);
        mylen += cid->oldlen/2;
        for (x=0;x<len;x++) 
-               buf[x+cid->oldlen/2] = ast_mulaw[ubuf[x]];
+               buf[x+cid->oldlen/2] = AST_MULAW(ubuf[x]);
        while(mylen >= 80) {
                olen = mylen;
                res = fsk_serie(&cid->fskd, buf, &mylen, &b);
@@ -239,7 +241,7 @@ int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len)
                                        }
                                } else {
                                        /* SDMF */
-                                       strncpy(cid->number, cid->rawdata + 8, sizeof(cid->number));
+                                       strncpy(cid->number, cid->rawdata + 8, sizeof(cid->number)-1);
                                }
                                /* Update flags */
                                cid->flags = 0;
@@ -346,57 +348,6 @@ static void callerid_genmsg(char *msg, int size, char *number, char *name, int f
        
 }
 
-static inline float callerid_getcarrier(float *cr, float *ci, int bit)
-{
-       /* Move along.  There's nothing to see here... */
-       float t;
-       t = *cr * dr[bit] - *ci * di[bit];
-       *ci = *cr * di[bit] + *ci * dr[bit];
-       *cr = t;
-       
-       t = 2.0 - (*cr * *cr + *ci * *ci);
-       *cr *= t;
-       *ci *= t;
-       return *cr;
-}      
-
-#define PUT_BYTE(a) do { \
-       *(buf++) = (a); \
-       bytes++; \
-} while(0)
-
-#define PUT_AUDIO_SAMPLE(y) do { \
-       int index = (short)(rint(8192.0 * (y))); \
-       *(buf++) = ast_lin2mu[index + 32768]; \
-       bytes++; \
-} while(0)
-       
-#define PUT_CLID_MARKMS do { \
-       int x; \
-       for (x=0;x<8;x++) \
-               PUT_AUDIO_SAMPLE(callerid_getcarrier(&cr, &ci, 1)); \
-} while(0)
-
-#define PUT_CLID_BAUD(bit) do { \
-       while(scont < clidsb) { \
-               PUT_AUDIO_SAMPLE(callerid_getcarrier(&cr, &ci, bit)); \
-               scont += 1.0; \
-       } \
-       scont -= clidsb; \
-} while(0)
-
-
-#define PUT_CLID(byte) do { \
-       int z; \
-       unsigned char b = (byte); \
-       PUT_CLID_BAUD(0);       /* Start bit */ \
-       for (z=0;z<8;z++) { \
-               PUT_CLID_BAUD(b & 1); \
-               b >>= 1; \
-       } \
-       PUT_CLID_BAUD(1);       /* Stop bit */ \
-} while(0);    
-
 int callerid_generate(unsigned char *buf, char *number, char *name, int flags, int callwaiting)
 {
        int bytes=0;
@@ -486,7 +437,7 @@ int ast_callerid_parse(char *instr, char **name, char **location)
                        return 0;
                }
        } else {
-               strncpy(tmp, instr, sizeof(tmp));
+               strncpy(tmp, instr, sizeof(tmp)-1);
                ast_shrink_phone_number(tmp);
                if (ast_isphonenumber(tmp)) {
                        /* Assume it's just a location */
@@ -508,7 +459,7 @@ static int __ast_callerid_generate(unsigned char *buf, char *callerid, int callw
        char *n, *l;
        if (!callerid)
                return callerid_generate(buf, NULL, NULL, 0, callwaiting);
-       strncpy(tmp, callerid, sizeof(tmp));
+       strncpy(tmp, callerid, sizeof(tmp)-1);
        if (ast_callerid_parse(tmp, &n, &l)) {
                ast_log(LOG_WARNING, "Unable to parse '%s' into CallerID name & number\n", callerid);
                return callerid_generate(buf, NULL, NULL, 0, callwaiting);
index 74ab878..b251c0b 100755 (executable)
--- a/channel.c
+++ b/channel.c
@@ -19,6 +19,7 @@
 #include <signal.h>
 #include <errno.h>
 #include <unistd.h>
+#include <asterisk/frame.h>
 #include <asterisk/sched.h>
 #include <asterisk/options.h>
 #include <asterisk/channel.h>
@@ -63,6 +64,30 @@ struct ast_channel *channels = NULL;
    
 static pthread_mutex_t chlock = PTHREAD_MUTEX_INITIALIZER;
 
+int ast_check_hangup(struct ast_channel *chan)
+{
+time_t myt;
+
+         /* if soft hangup flag, return true */
+       if (chan->softhangup) return 1;
+         /* if no hangup scheduled, just return here */
+       if (!chan->whentohangup) return 0;
+       time(&myt); /* get current time */
+         /* return, if not yet */
+       if (chan->whentohangup > myt) return 0;
+       chan->softhangup = 1;
+       return 1;
+}
+
+void ast_channel_setwhentohangup(struct ast_channel *chan, time_t offset)
+{
+time_t myt;
+
+       time(&myt);
+       chan->whentohangup = myt + offset;
+       return;
+}
+
 int ast_channel_register(char *type, char *description, int capabilities,
                struct ast_channel *(*requester)(char *type, int format, void *data))
 {
@@ -87,8 +112,8 @@ int ast_channel_register(char *type, char *description, int capabilities,
                PTHREAD_MUTEX_UNLOCK(&chlock);
                return -1;
        }
-       strncpy(chan->type, type, sizeof(chan->type));
-       strncpy(chan->description, description, sizeof(chan->description));
+       strncpy(chan->type, type, sizeof(chan->type)-1);
+       strncpy(chan->description, description, sizeof(chan->description)-1);
        chan->capabilities = capabilities;
        chan->requester = requester;
        chan->next = NULL;
@@ -180,7 +205,7 @@ struct ast_channel *ast_channel_alloc(void)
                        if (tmp->sched) {
                                for (x=0;x<AST_MAX_FDS;x++)
                                        tmp->fds[x] = -1;
-                               strncpy(tmp->name, "**Unknown**", sizeof(tmp->name));
+                               strncpy(tmp->name, "**Unknown**", sizeof(tmp->name)-1);
                                tmp->pvt = pvt;
                                tmp->state = AST_STATE_DOWN;
                                tmp->stack = -1;
@@ -188,10 +213,12 @@ struct ast_channel *ast_channel_alloc(void)
                                tmp->appl = NULL;
                                tmp->data = NULL;
                                pthread_mutex_init(&tmp->lock, NULL);
-                               strncpy(tmp->context, "default", sizeof(tmp->context));
-                               strncpy(tmp->language, defaultlanguage, sizeof(tmp->language));
-                               strncpy(tmp->exten, "s", sizeof(tmp->exten));
+                               strncpy(tmp->context, "default", sizeof(tmp->context)-1);
+                               strncpy(tmp->language, defaultlanguage, sizeof(tmp->language)-1);
+                               strncpy(tmp->exten, "s", sizeof(tmp->exten)-1);
                                tmp->priority=1;
+                               tmp->amaflags = ast_default_amaflags;
+                               strncpy(tmp->accountcode, ast_default_accountcode, sizeof(tmp->accountcode)-1);
                                tmp->next = channels;
                                channels= tmp;
                        } else {
@@ -276,6 +303,8 @@ void ast_channel_free(struct ast_channel *chan)
                free(chan->dnid);
        if (chan->callerid)
                free(chan->callerid);   
+       if (chan->hidden_callerid)
+               free(chan->hidden_callerid);
        pthread_mutex_destroy(&chan->lock);
        free(chan->pvt);
        free(chan);
@@ -330,6 +359,13 @@ int ast_hangup(struct ast_channel *chan)
                ast_stopstream(chan);
        if (chan->sched)
                sched_context_destroy(chan->sched);
+       if (chan->cdr) {
+               /* End the CDR if it hasn't already */
+               ast_cdr_end(chan->cdr);
+               /* Post and Free the CDR */
+               ast_cdr_post(chan->cdr);
+               ast_cdr_free(chan->cdr);
+       }
        if (chan->blocking) {
                ast_log(LOG_WARNING, "Hard hangup called by thread %ld on %s, while fd "
                                        "is blocked by thread %ld in procedure %s!  Expect a failure\n",
@@ -380,7 +416,7 @@ int ast_answer(struct ast_channel *chan)
 {
        int res = 0;
        /* Stop if we're a zombie or need a soft hangup */
-       if (chan->zombie || chan->softhangup) 
+       if (chan->zombie || ast_check_hangup(chan)) 
                return -1;
        switch(chan->state) {
        case AST_STATE_RINGING:
@@ -388,6 +424,8 @@ int ast_answer(struct ast_channel *chan)
                if (chan->pvt->answer)
                        res = chan->pvt->answer(chan);
                chan->state = AST_STATE_UP;
+               if (chan->cdr)
+                       ast_cdr_answer(chan->cdr);
                return res;
                break;
        case AST_STATE_UP:
@@ -557,7 +595,7 @@ char ast_waitfordigit(struct ast_channel *c, int ms)
        struct ast_frame *f;
        char result = 0;
        /* Stop if we're a zombie or need a soft hangup */
-       if (c->zombie || c->softhangup) 
+       if (c->zombie || ast_check_hangup(c)) 
                return -1;
        /* Wait for a digit, no more than ms milliseconds total. */
        while(ms && !result) {
@@ -598,7 +636,7 @@ struct ast_frame *ast_read(struct ast_channel *chan)
        }
 
        /* Stop if we're a zombie or need a soft hangup */
-       if (chan->zombie || chan->softhangup) {
+       if (chan->zombie || ast_check_hangup(chan)) {
                pthread_mutex_unlock(&chan->lock);
                return NULL;
        }
@@ -634,14 +672,20 @@ struct ast_frame *ast_read(struct ast_channel *chan)
                }
        }
        /* Make sure we always return NULL in the future */
-       if (!f)
+       if (!f) {
                chan->softhangup = 1;
-       else if (chan->deferdtmf && f->frametype == AST_FRAME_DTMF) {
+               /* End the CDR if appropriate */
+               if (chan->cdr)
+                       ast_cdr_end(chan->cdr);
+       } else if (chan->deferdtmf && f->frametype == AST_FRAME_DTMF) {
                if (strlen(chan->dtmfq) < sizeof(chan->dtmfq) - 2)
                        chan->dtmfq[strlen(chan->dtmfq)] = f->subclass;
                else
                        ast_log(LOG_WARNING, "Dropping deferred DTMF digits on %s\n", chan->name);
                f = &null_frame;
+       } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_ANSWER)) {
+               /* Answer the CDR */
+               ast_cdr_answer(chan->cdr);
        }
        pthread_mutex_unlock(&chan->lock);
 
@@ -652,7 +696,7 @@ int ast_indicate(struct ast_channel *chan, int condition)
 {
        int res = -1;
        /* Stop if we're a zombie or need a soft hangup */
-       if (chan->zombie || chan->softhangup) 
+       if (chan->zombie || ast_check_hangup(chan)) 
                return -1;
        if (chan->pvt->indicate) {
                res = chan->pvt->indicate(chan, condition);
@@ -663,11 +707,40 @@ int ast_indicate(struct ast_channel *chan, int condition)
        return res;
 }
 
+int ast_recvchar(struct ast_channel *chan, int timeout)
+{
+       int res,ourto,c;
+       struct ast_frame *f;
+       
+       ourto = timeout;
+       for(;;)
+          {
+               if (ast_check_hangup(chan)) return -1;
+               res = ast_waitfor(chan,ourto);
+               if (res <= 0) /* if timeout */
+                  {
+                       return 0;
+                  }
+               ourto = res;
+               f = ast_read(chan);
+               if (f == NULL) return -1; /* if hangup */
+               if ((f->frametype == AST_FRAME_CONTROL) &&
+                   (f->subclass == AST_CONTROL_HANGUP)) return -1; /* if hangup */
+               if (f->frametype == AST_FRAME_TEXT)  /* if a text frame */
+                  {
+                       c = *((char *)f->data);  /* get the data */
+                       ast_frfree(f);
+                       return(c);
+                  }
+               ast_frfree(f);
+       }
+}
+
 int ast_sendtext(struct ast_channel *chan, char *text)
 {
        int res = 0;
        /* Stop if we're a zombie or need a soft hangup */
-       if (chan->zombie || chan->softhangup) 
+       if (chan->zombie || ast_check_hangup(chan)) 
                return -1;
        CHECK_BLOCKING(chan);
        if (chan->pvt->send_text)
@@ -681,7 +754,7 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
        int res = -1;
        struct ast_frame *f;
        /* Stop if we're a zombie or need a soft hangup */
-       if (chan->zombie || chan->softhangup) 
+       if (chan->zombie || ast_check_hangup(chan)) 
                return -1;
        /* Handle any pending masquerades */
        if (chan->masq) {
@@ -699,10 +772,13 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
                ast_log(LOG_WARNING, "Don't know how to handle control frames yet\n");
                break;
        case AST_FRAME_DTMF:
-               
                if (chan->pvt->send_digit)
                        res = chan->pvt->send_digit(chan, fr->subclass);
                break;
+       case AST_FRAME_TEXT:
+               if (chan->pvt->send_text)
+                       res = chan->pvt->send_text(chan, (char *) fr->data);
+               break;
        default:
                if (chan->pvt->write) {
                        if (chan->pvt->writetrans) {
@@ -744,7 +820,7 @@ int ast_set_write_format(struct ast_channel *chan, int fmts)
        /* Build a translation path from the user write format to the raw writing format */
        chan->pvt->writetrans = ast_translator_build_path(chan->pvt->rawwriteformat, chan->writeformat);
        if (option_debug)
-               ast_log(LOG_DEBUG, "Set channel %s to format %d\n", chan->name, chan->writeformat);
+               ast_log(LOG_DEBUG, "Set channel %s to write format %d\n", chan->name, chan->writeformat);
        return 0;
 }
 
@@ -772,6 +848,8 @@ int ast_set_read_format(struct ast_channel *chan, int fmts)
                ast_translator_free_path(chan->pvt->readtrans);
        /* Build a translation path from the raw read format to the user reading format */
        chan->pvt->readtrans = ast_translator_build_path(chan->readformat, chan->pvt->rawreadformat);
+       if (option_debug)
+               ast_log(LOG_DEBUG, "Set channel %s to read format %d\n", chan->name, chan->readformat);
        return 0;
 }
 
@@ -818,7 +896,7 @@ int ast_call(struct ast_channel *chan, char *addr, int timeout)
        int res = -1;
        /* Stop if we're a zombie or need a soft hangup */
        pthread_mutex_lock(&chan->lock);
-       if (!chan->zombie && !chan->softhangup) 
+       if (!chan->zombie && !ast_check_hangup(chan)) 
                if (chan->pvt->call)
                        res = chan->pvt->call(chan, addr, timeout);
        pthread_mutex_unlock(&chan->lock);
@@ -831,7 +909,7 @@ int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int fti
        int to = ftimeout;
        char d;
        /* Stop if we're a zombie or need a soft hangup */
-       if (c->zombie || c->softhangup) 
+       if (c->zombie || ast_check_hangup(c)) 
                return -1;
        if (!len)
                return -1;
@@ -982,7 +1060,7 @@ static int ast_do_masquerade(struct ast_channel *original)
        clone->masqr = NULL;
                
        /* Copy the name from the clone channel */
-       strncpy(original->name, clone->name, sizeof(original->name));
+       strncpy(original->name, clone->name, sizeof(original->name)-1);
 
        /* Mangle the name of the clone channel */
        strncat(clone->name, "<MASQ>", sizeof(clone->name));
@@ -1019,6 +1097,8 @@ static int ast_do_masquerade(struct ast_channel *original)
        /* Copy the FD's */
        for (x=0;x<AST_MAX_FDS;x++)
                original->fds[x] = clone->fds[x];
+       /* Presense of ADSI capable CPE follows clone */
+       original->adsicpe = clone->adsicpe;
        /* Bridge remains the same */
        /* CDR fields remain the same */
        /* XXX What about blocking, softhangup, blocker, and lock and blockproc? XXX */
@@ -1096,7 +1176,7 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
        int res;
        int nativefailed=0;
        /* Stop if we're a zombie or need a soft hangup */
-       if (c0->zombie || c0->softhangup || c1->zombie || c1->softhangup) 
+       if (c0->zombie || ast_check_hangup(c0) || c1->zombie || ast_check_hangup(c1)) 
                return -1;
        if (c0->bridge) {
                ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 
@@ -1116,7 +1196,7 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
        cs[1] = c1;
        for (/* ever */;;) {
                /* Stop if we're a zombie or need a soft hangup */
-               if (c0->zombie || c0->softhangup || c1->zombie || c1->softhangup) {
+               if (c0->zombie || ast_check_hangup(c0) || c1->zombie || ast_check_hangup(c1)) {
                        *fo = NULL;
                        if (who) *rc = who;
                        res = 0;
@@ -1233,3 +1313,4 @@ int ast_channel_setoption(struct ast_channel *chan, int option, void *data, int
        }
        return 0;
 }
+
diff --git a/configs/adsi.conf.sample b/configs/adsi.conf.sample
new file mode 100755 (executable)
index 0000000..0f36f80
--- /dev/null
@@ -0,0 +1,8 @@
+;
+; Sample ADSI Configuration file
+;
+[intro]
+alignment = center
+greeting => Welcome to the
+greeting => Asterisk
+greeting => Open Source PBX
index abff988..9ea3206 100755 (executable)
@@ -19,6 +19,7 @@ context=default
 ; dms100:        Nortel DMS100
 ; 4ess:           AT&T 4ESS
 ; 5ess:                  Lucent 5ESS
+; euroisdn:       EuroISDN
 ;
 switchtype=national
 ;
@@ -99,6 +100,21 @@ immediate=no
 ;
 ;callerid=2564286000
 ;
+; AMA flags affects the recording of Call Detail Records.  If specified
+; it may be 'default', 'omit', 'billing', or 'documentation'.
+;
+;amaflags=default
+;
+; Channels may be associated with an account code to ease
+; billing
+;
+;accountcode=lss0101
+;
+; ADSI (Analog Display Services Interface) can be enabled on a per-channel
+; basis if you have (or may have) ADSI compatible CPE equipment
+;
+;adsi=yes
+;
 ; Each channel consists of the channel number or range.  It
 ; inherits the parameters that were specified above its declaration
 ;
@@ -156,6 +172,6 @@ stripmsd=1
 ; you will want to create a single "group" for all channels of the PRI.
 ;
 ; switchtype = national
-; sig = pri_cpe
+; signalling = pri_cpe
 ; group = 2
 ; channel => 1-23
diff --git a/include/asterisk/adsi.h b/include/asterisk/adsi.h
new file mode 100755 (executable)
index 0000000..a3d538d
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+ * Asterisk -- A telephony toolkit for Linux.
+ *
+ * ADSI Support (built upon Caller*ID) 
+ * 
+ * Copyright (C) 1999, Mark Spencer
+ *
+ * Mark Spencer <markster@linux-support.net>
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License.
+ *
+ * Includes code and algorithms from the Zapata library.
+ *
+ */
+
+#ifndef _ADSI_H
+#define _ADSI_H
+#include <asterisk/callerid.h>
+
+/* ADSI Message types */
+#define ADSI_MSG_DISPLAY       132
+#define ADSI_MSG_DOWNLOAD      133
+
+/* ADSI Parameters (display) */
+#define ADSI_LOAD_SOFTKEY      128
+#define ADSI_INIT_SOFTKEY_LINE 129
+#define ADSI_LOAD_VIRTUAL_DISP 130
+#define ADSI_LINE_CONTROL      131
+#define ADSI_INFORMATION       132
+#define ADSI_DISC_SESSION      133
+#define ADSI_SWITCH_TO_DATA    134
+#define ADSI_SWITCH_TO_VOICE   135
+#define ADSI_CLEAR_SOFTKEY     136
+#define ADSI_INPUT_CONTROL     137
+#define ADSI_INPUT_FORMAT      138
+#define ADSI_SWITCH_TO_PERIPH  139
+#define ADSI_MOVE_DATA         140
+#define ADSI_LOAD_DEFAULT      141
+#define ADSI_CONNECT_SESSION   142
+#define ADSI_CLEAR_TYPE_AHEAD  143
+#define ADSI_DISPLAY_CALL_BUF  144
+#define ADSI_CLEAR_CALL_BUF    145
+#define ADSI_SWITCH_TO_ALT     146
+#define ADSI_SWITCH_TO_GRAPHICS        147
+#define ADSI_CLEAR_SCREEN      148
+#define ADSI_QUERY_CONFIG      149
+#define ADSI_QUERY_CPEID       150
+#define ADSI_SWITCH_TO_APP     151
+
+/* Feature download messages */
+#define ADSI_LOAD_SOFTKEY_TABLE        128     /* Conveniently identical to the soft version */
+#define ADSI_LOAD_PREDEF_DISP  129     /* Load predefined display */
+#define ADSI_LOAD_SCRIPT       130
+#define ADSI_DOWNLOAD_CONNECT  131
+#define ADSI_DOWNLOAD_DISC     132
+
+/* Special return string codes */
+#define ADSI_ENCODED_DTMF      0x80    /* Transmit following chars with encoded dtmf */
+#define ADSI_ON_HOOK           0x81    /* Open switch-hook */
+#define ADSI_OFF_HOOK          0x82    /* Close switch-hook */
+#define ADSI_FLASH             0x83    /* Flash switch-hook */
+#define ADSI_DIAL_TONE_DETECT  0x84    /* Wait for dialtone */
+#define ADSI_LINE_NUMBER       0x85    /* Send current line number using DTMF/encoded DTMF */
+#define ADSI_BLANK             0x86    /* Blank (does nothing) */
+#define ADSI_SEND_CHARS                0x87    /* Send collected digits/characters */
+#define ADSI_CLEAR_CHARS       0x88    /* Clear characters/digits collected */
+#define ADSI_BACKSPACE         0x89    /* Erase last collected digit */
+#define ADSI_TAB_COLUMN                0x8A    /* Display specified display column of current line */
+#define ADSI_GOTO_LINE         0x8B    /* Go to given page and line number */
+#define ADSI_GOTO_LINE_REL     0x8C    /* Go to given line (relative to current) */
+#define ADSI_PAGE_UP           0x8D    /* Go up one page */
+#define ADSI_PAGE_DOWN         0x8E    /* Go down one page */
+#define ADSI_EXTENDED_DTMF     0x8F    /* Send DTMF tones for 250ms instead of 60 ms */
+#define ADSI_DELAY             0x90    /* Delay for given # (times 10) of ms */
+#define ADSI_DIAL_PULSE_ONE    0x91    /* Send a dial pulse "1" */
+#define ADSI_SWITCH_TO_DATA2   0x92    /* Switch CPE to data mode */
+#define ADSI_SWITCH_TO_VOICE2  0x93    /* Switch CPE to voice mode */
+#define ADSI_DISP_CALL_BUF     0x94    /* Display specified call buffer */
+#define ADSI_CLEAR_CALL_BUF    0x95    /* Clear specified call buffer */
+
+#ifdef __ADSI_CPE
+/* These messages are reserved for the ADSI CPE only */
+#define ADSI_DISPLAY_CONTROL   0x98    /* Store predefined display identified next / Display status display page */
+#define ADSI_DISPLAY_SOFT_KEYS 0x99    /* Display the script soft keys identified next */
+#define ADSI_CHANGE_STATE      0x9A    /* Change state of service script */
+#define ADSI_START_CLEAR_TIMER 0x9B    /* Start / Clear timer */
+#define ADSI_SET_SCRIPT_FLAG   0x9C    /* Set / clear a script flag */
+#define ADSI_JUMP_TO_SUBSCRIPT 0x9D    /* Jump to specified subscript */
+#define ADSI_EVENT_22_TRIGGER  0x9E    /* Trigger an occurance of event 22 */
+#define ADSI_EVENT_23_TRIGGER  0x9f    /* Trigger an occurance of event 23 */
+#define ADSI_EXIT              0xA0    /* Exit the service script interpreter */
+#endif
+
+/* Display pages */
+#define ADSI_INFO_PAGE 0x0
+#define ADSI_COMM_PAGE 0x1
+
+#define ADSI_KEY_APPS  16      /* 16 to 33 reserved for applications */
+
+/* Justification */
+#define ADSI_JUST_LEFT 0x2
+#define ADSI_JUST_RIGHT 0x1
+#define ADSI_JUST_CENT  0x0    /* Center */
+#define ADSI_JUST_IND  0x3     /* Indent */
+
+#define ADSI_KEY_SKT   0x80    /* Load from SKT */
+#define ADSI_KEY_HILITE        0x40    /* Highlight key */
+
+#define ADSI_DIR_FROM_LEFT (0)
+#define ADSI_DIR_FROM_RIGHT (1)
+
+//! Perform Asterisk ADSI initialization (for channel drivers that want
+//   to support ADSI when the handset is first lifted) */
+/*! 
+ * \param chan Channel to initialize for ADSI (if supported)
+ * 
+ * Returns 0 on success (or adsi unavailable) and -1 on hangup
+ * 
+ */
+extern int adsi_channel_init(struct ast_channel *chan);
+
+extern int adsi_begin_download(struct ast_channel *chan, char *service, char *fdn, char *sec, int version);
+
+extern int adsi_end_download(struct ast_channel *chan);
+
+//! Restore ADSI initialization (for applications that play with ADSI
+//  and want to restore it to normal.  If you touch "INFO" then you
+//  have to use the adsi_channel_init again instead.
+/*!
+ * \param chan Channel to restore
+ * 
+ * Returns 0 on success (or adsi unavailable) and -1 on hangup
+ *
+ */
+extern int adsi_channel_restore(struct ast_channel *chan);
+
+//! Display some stuff on the screen
+/*!
+ * \param chan Channel to display on
+ * \param lines NULL-terminated list of things to print (no more than 4 recommended)
+ * \param align list of alignments to use (ADSI_JUST_LEFT, ADSI_JUST_RIGHT, ADSI_JUST_CEN, etc..)
+ *
+ * Return 0 on success (or adsi unavailable) and -1 on hangup
+ *
+ */
+extern int adsi_print(struct ast_channel *chan, char **lines, int *align);
+
+//! Check if scripts for a given app are already loaded.  Version may be -1
+//  if any version is okay, or 0-255 for a specific version.
+/*!
+ * \param chan Channel to test for loaded app
+ * \param app Four character app name (must be unique to your application)
+ * \param ver optional version number
+ * \param data Non-zero if you want to be put in data mode
+ *
+ * Returns 0 if scripts is not loaded or not an ADSI CPE.  Returns -1
+ * on hangup.  Returns 1 if script already loaded.
+ */
+extern int adsi_load_session(struct ast_channel *chan, unsigned char *app, int ver, int data);
+extern int adsi_unload_session(struct ast_channel *chan);
+
+/* ADSI Layer 2 transmission functions */
+extern int adsi_transmit_messages(struct ast_channel *chan, unsigned char **msg, int *msglen, int *msgtype);
+extern int adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype);
+
+/* ADSI Layer 3 creation functions */
+
+//! Connects an ADSI Display Session */
+/*!
+ * \param buf Character buffer to create parameter in (must have at least 256 free)
+ * \param fdn Optional 4 byte Feature Download Number (for loading soft keys)
+ * \param ver Optional version number (0-255, or -1 to omit)
+ *
+ * Returns number of bytes added to buffer or -1 on error.
+ *
+ */
+
+extern int adsi_connect_session(unsigned char *buf, unsigned char *fdn, int ver);
+
+//! Begin an ADSI script download */
+/*!
+ * \param buf Character buffer to create parameter in (must have at least 256 free)
+ * \param service, a 1-18 byte name of the feature
+ * \param fdn 4 byte Feature Download Number (for loading soft keys)
+ * \param sec 4 byte vendor security code
+ * \param ver version number (0-255, or -1 to omit)
+ *
+ * Returns number of bytes added to buffer or -1 on error.
+ *
+ */
+
+extern int adsi_download_connect(unsigned char *buf, unsigned char *service, unsigned char *fdn, unsigned char *sec, int ver);
+
+//! Disconnects a running session
+/*!
+ * \param buf Character buffer to create parameter in (must have at least 256 free)
+ *
+ * Returns number of bytes added to buffer or -1 on error.
+ *
+ */
+extern int adsi_disconnect_session(unsigned char *buf);
+
+//! Disconnects (and hopefully saves) a downloaded script
+/*!
+ * \param buf Character buffer to create parameter in (must have at least 256 free)
+ *
+ * Returns number of bytes added to buffer or -1 on error.
+ *
+ */
+extern int adsi_download_disconnect(unsigned char *buf);
+
+//! Puts CPE in data mode...
+/*!
+ * \param buf Character buffer to create parameter in (must have at least 256 free)
+ *
+ * Returns number of bytes added to buffer or -1 on error.
+ *
+ */
+extern int adsi_data_mode(unsigned char *buf);
+
+//! Puts CPE in voice mode...
+/*!
+ * \param buf Character buffer to create parameter in (must have at least 256 free)
+ * \param when (a time in seconds) to make the switch
+ *
+ * Returns number of bytes added to buffer or -1 on error.
+ *
+ */
+extern int adsi_voice_mode(unsigned char *buf, int when);
+
+//! Returns non-zero if Channel does or might support ADSI
+/*!
+ * \param chan Channel to check
+ *
+ */
+extern int adsi_available(struct ast_channel *chan);
+
+//! Loads a line of info into the display */
+/*!
+ * \param buf Character buffer to create parameter in (must have at least 256 free)
+ * \param page Page to load (ADSI_COMM_PAGE or ADSI_INFO_PAGE)
+ * \param line Line number to load (1-4 for Comm page, 1-33 for info page)
+ * \param just Line justification (ADSI_JUST_LEFT, ADSI_JUST_RIGHT, ADSI_JUST_CENT, ADSI_JUST_IND)
+ * \param wrap Wrap (1 = yes, 0 = no)
+ * \param col1 Text to place in first column
+ * \param col2 Text to place in second column
+ *
+ * Returns number of bytes added to buffer or -1 on error.
+ *
+ */
+
+extern int adsi_display(unsigned char *buf, int page, int line, int just, int wrap, unsigned char *col1, unsigned char *col2);
+
+//! Sets the current line and page */
+/*!
+ * \param buf Character buffer to create parameter in (must have at least 256 free)
+ * \param page Which page (ADSI_COMM_PAGE or ADSI_INFO_PAGE)
+ * \param line Line number (1-33 for info page, 1-4 for comm page)
+ *
+ * Returns number of bytes added to buffer or -1 on error.
+ *
+ */
+
+extern int adsi_set_line(unsigned char *buf, int page, int line);
+
+//! Creates "load soft key" parameters
+/*! 
+ * \param buf Character buffer to create parameter in (must have at least 256 free)
+ * \param key Key code from 2 to 33, for which key we are loading
+ * \param llabel Long label for key (1-18 bytes)
+ * \param slabel Short label for key (1-7 bytes)
+ * \param ret Optional return sequence (NULL for none)
+ * \param data whether to put CPE in data mode before sending digits
+ *
+ * Returns number of bytes added to buffer or -1 on error.
+ *
+ */
+extern int adsi_load_soft_key(unsigned char *buf, int key, unsigned char *llabel, unsigned char *slabel, unsigned char *ret, int data);
+
+//! Set which soft keys should be displayed
+/*!
+ * \param buf Character buffer to create parameter in (must have at least 256 free)
+ * \param keys Array of 6 unsigned chars with the key numbers, may be OR'd with ADSI_KEY_HILITE
+ *
+ * Returns number of bytes added to buffer or -1 on error.
+ *
+ */
+extern int adsi_set_keys(unsigned char *buf, unsigned char *keys);
+
+//! Set input information
+/*!
+ * \param buf Character buffer to create parameter in (must have at least 256 free)
+ * \param page Which page to input on (ADSI_COMM_PAGE or ADSI_INFO_PAGE)
+ * \param line Line number to input on
+ * \param display Set to zero to obscure input, or 1 to leave visible
+ * \param format Format number to use (0-7)
+ * \param just Justification (left, right center, indent)
+ *
+ * Returns number of bytes added to buffer or -1 on error.
+ *
+ */
+extern int adsi_input_control(unsigned char *buf, int page, int line, int display, int format, int just);
+
+//! Set input format
+/*!
+ * \param buf Character buffer to create parameter in (must have at least 256 free)
+ * \param num Which format we are setting
+ * \param dir Which direction (ADSI_DIR_FROM_LEFT or ADSI_DIR_FROM_RIGHT)
+ * \param wrap Set to 1 to permit line wrap, or 0 if not
+ * \param format1 Format for column 1
+ * \param format2 Format for column 2
+ *
+ * Returns number of bytes added to buffer or -1 on error.
+ *
+ */
+extern int adsi_input_format(unsigned char *buf, int num, int dir, int wrap, unsigned char *format1, unsigned char *format2);
+#endif
index 9f9e691..079a839 100755 (executable)
@@ -1,7 +1,7 @@
 /*
  * Asterisk -- A telephony toolkit for Linux.
  *
- * CallerID Generation support 
+ * CallerID (and other GR30) Generation support 
  * 
  * Copyright (C) 1999, Mark Spencer
  *
 struct callerid_state;
 typedef struct callerid_state CIDSTATE;
 
-/* CallerID Initialization */
+//! CallerID Initialization
+/*!
+ * Initializes the callerid system.  Mostly stuff for inverse FFT
+ */
 extern void callerid_init(void);
 
-/* Generates a CallerID FSK stream in ulaw
-   format suitable for transmission.  Assumes 8000 Hz.  Use NULL
-   for no number or "P" for "private".  If "buf" is supplied it will
-   use that buffer instead of allocating its own.  "buf" must be
-   at least 32000 bytes in size if you want to be sure you dont
-   have an overrun however.  Returns # of bytes written to buffer.
-   Use "O" or "P" in name */
+//! Generates a CallerID FSK stream in ulaw format suitable for transmission.
+/*!
+ * \param buf Buffer to use. If "buf" is supplied, it will use that buffer instead of allocating its own.  "buf" must be at least 32000 bytes in size of you want to be sure you don't have an overrun.
+ * \param number Use NULL for no number or "P" for "private"
+ * \param name name to be used
+ * \param callwaiting callwaiting flag
+ * This function creates a stream of callerid (a callerid spill) data in ulaw format. It returns the size
+ * (in bytes) of the data (if it returns a size of 0, there is probably an error)
+*/
 extern int callerid_generate(unsigned char *buf, char *number, char *name, int flags, int callwaiting);
 
-/* Create a callerID state machine */
+//! Create a callerID state machine
+/*!
+ * This function returns a malloc'd instance of the callerid_state data structure.
+ * Returns a pointer to a malloc'd callerid_state structure, or NULL on error.
+ */
 extern struct callerid_state *callerid_new(void);
 
-/* Read samples into the state machine.  Returns -1 on error, 0 for "needs more samples", and 1 for
-   callerID stuff complete */
-extern int callerid_feed(struct callerid_state *cid, unsigned char *buf, int samples);
-
-/* Extract info out of callerID state machine.  Flags are listed above */
+//! Read samples into the state machine.
+/*!
+ * \param cid Which state machine to act upon
+ * \param buffer containing your samples
+ * \param samples number of samples contained within the buffer.
+ *
+ * Send received audio to the Caller*ID demodulator.
+ * Returns -1 on error, 0 for "needs more samples", 
+ * and 1 if the CallerID spill reception is complete.
+ */
+extern int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int samples);
+
+//! Extract info out of callerID state machine.  Flags are listed above
+/*!
+ * \param cid Callerid state machine to act upon
+ * \param number Pass the address of a pointer-to-char (will contain the phone number)
+ * \param name Pass the address of a pointer-to-char (will contain the name)
+ * \param flags Pass the address of an int variable(will contain the various callerid flags)
+ *
+ * This function extracts a callerid string out of a callerid_state state machine.
+ * If no number is found, *number will be set to NULL.  Likewise for the name.
+ * Flags can contain any of the following:
+ * 
+ * Returns nothing.
+ */
 void callerid_get(struct callerid_state *cid, char **number, char **name, int *flags);
 
-/* Free a callerID state */
+//! Free a callerID state
+/*!
+ * \param cid This is the callerid_state state machine to free
+ * This function frees callerid_state cid.
+ */
 extern void callerid_free(struct callerid_state *cid);
 
-/* Generate Caller-ID spill from the "callerid" field of asterisk (in e-mail address like format) */
+//! Generate Caller-ID spill from the "callerid" field of asterisk (in e-mail address like format)
+/*!
+ * \param buf buffer for output samples. See callerid_generate() for details regarding buffer.
+ * \param astcid Asterisk format callerid string, taken from the callerid field of asterisk.
+ *
+ * Acts like callerid_generate except uses an asterisk format callerid string.
+ */
 extern int ast_callerid_generate(unsigned char *buf, char *astcid);
 
-/* Generate Caller-ID spill from the "callerid" field of asterisk (in e-mail address like format) 
-   but in a format suitable for Call Waiting(tm) Caller*ID(tm) */
+//! Generate Caller-ID spill from the "callerid" field of asterisk (in e-mail address like format) but in a format suitable for Call Waiting(tm)'s Caller*ID(tm)
+/*!
+ * See ast_callerid_generate for other details
+ */
 extern int ast_callerid_callwaiting_generate(unsigned char *buf, char *astcid);
 
-/* Destructively parse inbuf into name and location (or number) */
-extern int ast_callerid_parse(char *inbuf, char **name, char **location);
-
-/* Generate a CAS (CPE Alert Signal) tone for 'n' samples */
-extern int ast_callerid_gen_cas(unsigned char *outbuf, int len);
+//! Destructively parse inbuf into name and location (or number)
+/*!
+ * \param inbuf buffer of callerid stream (in audio form) to be parsed. Warning, data in buffer is changed.
+ * \param name address of a pointer-to-char for the name value of the stream.
+ * \param location address of a pointer-to-char for the phone number value of the stream.
+ * Parses callerid stream from inbuf and changes into useable form, outputed in name and location.
+ * Returns 0 on success, -1 on failure.
+ */
+extern int ast_callerid_parse(char *instr, char **name, char **location);
+
+//! Generate a CAS (CPE Alert Signal) tone for 'n' samples
+/*!
+ * \param outbuf Allocated buffer for data.  Must be at least 2400 bytes unless no SAS is desired
+ * \param sas Non-zero if CAS should be preceeded by SAS
+ * \param len How many samples to generate.
+ * Returns -1 on error (if len is less than 2400), 0 on success.
+ */
+extern int ast_gen_cas(unsigned char *outbuf, int sas, int len);
 
-/* Shrink a phone number in place to just digits (more accurately it just removes ()'s, .'s, and -'s...  */
+//! Shrink a phone number in place to just digits (more accurately it just removes ()'s, .'s, and -'s...
+/*!
+ * \param n The number to be stripped/shrunk
+ * Returns nothing important
+ */
 extern void ast_shrink_phone_number(char *n);
 
-/* Check if a string consists only of digits.  Returns non-zero if so */
+//! Check if a string consists only of digits.  Returns non-zero if so
+/*!
+ * \param n number to be checked.
+ * Returns 0 if n is a number, 1 if it's not.
+ */
 extern int ast_isphonenumber(char *n);
+
+
+/*
+ * Caller*ID and other GR-30 compatible generation
+ * routines (used by ADSI for example)
+ */
+
+extern float dr[4];
+extern float di[4];
+extern float clidsb;
+
+static inline float callerid_getcarrier(float *cr, float *ci, int bit)
+{
+       /* Move along.  There's nothing to see here... */
+       float t;
+       t = *cr * dr[bit] - *ci * di[bit];
+       *ci = *cr * di[bit] + *ci * dr[bit];
+       *cr = t;
+       
+       t = 2.0 - (*cr * *cr + *ci * *ci);
+       *cr *= t;
+       *ci *= t;
+       return *cr;
+}      
+
+#define PUT_BYTE(a) do { \
+       *(buf++) = (a); \
+       bytes++; \
+} while(0)
+
+#define PUT_AUDIO_SAMPLE(y) do { \
+       int index = (short)(rint(8192.0 * (y))); \
+       *(buf++) = AST_LIN2MU(index); \
+       bytes++; \
+} while(0)
+       
+#define PUT_CLID_MARKMS do { \
+       int x; \
+       for (x=0;x<8;x++) \
+               PUT_AUDIO_SAMPLE(callerid_getcarrier(&cr, &ci, 1)); \
+} while(0)
+
+#define PUT_CLID_BAUD(bit) do { \
+       while(scont < clidsb) { \
+               PUT_AUDIO_SAMPLE(callerid_getcarrier(&cr, &ci, bit)); \
+               scont += 1.0; \
+       } \
+       scont -= clidsb; \
+} while(0)
+
+
+#define PUT_CLID(byte) do { \
+       int z; \
+       unsigned char b = (byte); \
+       PUT_CLID_BAUD(0);       /* Start bit */ \
+       for (z=0;z<8;z++) { \
+               PUT_CLID_BAUD(b & 1); \
+               b >>= 1; \
+       } \
+       PUT_CLID_BAUD(1);       /* Stop bit */ \
+} while(0);    
+
+
 #endif
index ef6cc4f..1d2b9c7 100755 (executable)
@@ -79,191 +79,418 @@ static inline int __ast_pthread_mutex_unlock(char *filename, int lineno, char *f
 #define ast_pthread_mutex_unlock pthread_mutex_unlock
 #endif
 
+//! Max length of an extension
+#define AST_MAX_EXTENSION 80
+
+#include <asterisk/cdr.h>
+
+
 #define AST_CHANNEL_NAME 80
 #define AST_CHANNEL_MAX_STACK 32
 
 #define MAX_LANGUAGE 20
 
-/* Max length an extension can be (unique) is this number */
-#define AST_MAX_EXTENSION 80
 
 #define AST_MAX_FDS 4
 
+//! Main Channel structure associated with a channel.
+/*! 
+ * This is the side of it mostly used by the pbx and call management.
+ */
 struct ast_channel {
-       char name[AST_CHANNEL_NAME];            /* ASCII Description of channel name */
-       char language[MAX_LANGUAGE];            /* Language requested */
-       char *type;                             /* Type of channel */
-       int fds[AST_MAX_FDS];                   /* File descriptor for channel -- Drivers will poll
-                                                                  on these file descriptors, so at least one must be
-                                                                  non -1.  */
+       /*! ASCII Description of channel name */
+       char name[AST_CHANNEL_NAME];            
+       /*! Language requested */
+       char language[MAX_LANGUAGE];            
+       /*! Type of channel */
+       char *type;                             
+       /*! File descriptor for channel -- Drivers will poll on these file descriptors, so at least one must be non -1.  */
+       int fds[AST_MAX_FDS];                   
                                                   
-       struct ast_channel *bridge;                     /* Who are we bridged to, if we're bridged */
-       struct ast_channel *masq;                       /* Channel that will masquerade as us */
-       struct ast_channel *masqr;                      /* Who we are masquerading as */
-       int cdrflags;                                           /* Call Detail Record Flags */                                             
-
-       int blocking;                                           /* Whether or not we're blocking */
-       int softhangup;                                         /* Whether or not we have been hung up */
-       int zombie;                                                     /* Non-zero if this is a zombie channel */      
-       pthread_t blocker;                                      /* If anyone is blocking, this is them */
-       pthread_mutex_t lock;                           /* Lock, can be used to lock a channel for some operations */
-       char *blockproc;                                        /* Procedure causing blocking */
+       /*! Who are we bridged to, if we're bridged */
+       struct ast_channel *bridge;             
+       /*! Channel that will masquerade as us */
+       struct ast_channel *masq;               
+       /*! Who we are masquerading as */
+       struct ast_channel *masqr;              
+       /*! Call Detail Record Flags */
+       int cdrflags;                                                                              
+       /*! Whether or not we're blocking */
+       int blocking;                           
+       /*! Whether or not we have been hung up */
+       int softhangup;                         
+       /*! Non-zero if this is a zombie channel */
+       int zombie;                                     
+       /*! Non-zero, set to actual time when channel is to be hung up */
+       time_t  whentohangup;
+       /*! If anyone is blocking, this is them */
+       pthread_t blocker;                      
+       /*! Lock, can be used to lock a channel for some operations */
+       pthread_mutex_t lock;                   
+       /*! Procedure causing blocking */
+       char *blockproc;                        
+
+       /*! Current application */
+       char *appl;                             
+       /*! Data passed to current application */
+       char *data;                             
        
-       char *appl;                                                     /* Current application */
-       char *data;                                                     /* Data passed to current application */
-       
-       int exception;                                          /* Has an exception been detected */
-       int fdno;                                                       /* Which fd had an event detected on */
-       struct sched_context *sched;            /* Schedule context */
-
-       int streamid;                                   /* For streaming playback, the schedule ID */
-       struct ast_filestream *stream;  /* Stream itself. */
-       int oldwriteformat;                             /* Original writer format */
-
-       int state;                              /* State of line */
-       int rings;                              /* Number of rings so far */
-       int stack;                              /* Current level of application */
-
-       int nativeformats;              /* Kinds of data this channel can
-                                                          natively handle */
-       int readformat;                 /* Requested read format */
-       int writeformat;                /* Requested write format */
+       /*! Has an exception been detected */
+       int exception;                          
+       /*! Which fd had an event detected on */
+       int fdno;                               
+       /*! Schedule context */
+       struct sched_context *sched;            
+       /*! For streaming playback, the schedule ID */
+       int streamid;                           
+       /*! Stream itself. */
+       struct ast_filestream *stream;          
+       /*! Original writer format */
+       int oldwriteformat;                     
+
+
+       /*! State of line */
+       int state;                              
+       /*! Number of rings so far */
+       int rings;                              
+       /*! Current level of application */
+       int stack;                              
+
+
+       /*! Kinds of data this channel can natively handle */
+       int nativeformats;                      
+       /*! Requested read format */
+       int readformat;                         
+       /*! Requested write format */
+       int writeformat;                        
+
        
-       char *dnid;                             /* Malloc'd Dialed Number Identifier */
-       char *callerid;                 /* Malloc'd Caller ID */
+       /*! Malloc'd Dialed Number Identifier */
+       char *dnid;                             
+       /*! Malloc'd Caller ID */
+       char *callerid;                         
+       /*! Malloc'd Hidden Caller*ID */
+       char *hidden_callerid;                  
+
        
-       char context[AST_MAX_EXTENSION];        /* Current extension context */
-       char exten[AST_MAX_EXTENSION];          /* Current extension number */
-       int priority;                                           /* Current extension priority */
-       void *app[AST_CHANNEL_MAX_STACK];       /* Application information -- see assigned numbers */
-       char dtmfq[AST_MAX_EXTENSION];          /* Any/all queued DTMF characters */
-       int deferdtmf;                                          /* Are DTMF digits being deferred */
-       struct ast_frame dtmff;                         /* DTMF frame */
+       /*! Current extension context */
+       char context[AST_MAX_EXTENSION];        
+       /*! Current extension number */
+       char exten[AST_MAX_EXTENSION];          
+       /* Current extension priority */
+       int priority;                                           
+       /*! Application information -- see assigned numbers */
+       void *app[AST_CHANNEL_MAX_STACK];       
+       /*! Any/all queued DTMF characters */
+       char dtmfq[AST_MAX_EXTENSION];          
+       /*! Are DTMF digits being deferred */
+       int deferdtmf;                          
+       /*! DTMF frame */
+       struct ast_frame dtmff;                 
+       /*! Private channel implementation details */
        struct ast_channel_pvt *pvt;
-                                               /* Private channel implementation details */
-       jmp_buf jmp[AST_CHANNEL_MAX_STACK];             /* Jump buffer used for returning from applications */
+
+                                               
+       /*! Jump buffer used for returning from applications */
+       jmp_buf jmp[AST_CHANNEL_MAX_STACK];     
+
        struct ast_pbx *pbx;
-       struct ast_channel *next;               /* For easy linking */
-};
+       /*! Set BEFORE PBX is started to determine AMA flags */
+       int     amaflags;                       
+       /*! Account code for billing */
+       char    accountcode[20];                
+       /*! Call Detail Record */
+       struct ast_cdr *cdr;                    
+       /*! Whether or not ADSI is detected on CPE */
+       int     adsicpe;
+       /*! For easy linking */
+       struct ast_channel *next;               
 
+};
 
 #define AST_CDR_TRANSFER       (1 << 0)
 #define AST_CDR_FORWARD                (1 << 1)
 #define AST_CDR_CALLWAIT       (1 << 2)
 #define AST_CDR_CONFERENCE     (1 << 3)
 
-/* Bits 0-15 of state are reserved for the state (up/down) of the line */
+#define AST_ADSI_UNKNOWN       (0)
+#define AST_ADSI_AVAILABLE     (1)
+#define AST_ADSI_UNAVAILABLE   (2)
+#define AST_ADSI_OFFHOOKONLY   (3)
 
-#define AST_STATE_DOWN         0               /* Channel is down and available */
-#define AST_STATE_RESERVED     1               /* Channel is down, but reserved */
-#define AST_STATE_OFFHOOK      2               /* Channel is off hook */
-#define AST_STATE_DIALING      3               /* Digits (or equivalent) have been dialed */
-#define AST_STATE_RING         4               /* Line is ringing */
-#define AST_STATE_RINGING      5               /* Remote end is ringing */
-#define AST_STATE_UP           6               /* Line is up */
-#define AST_STATE_BUSY         7               /* Line is busy */
+/* Bits 0-15 of state are reserved for the state (up/down) of the line */
+/*! Channel is down and available */
+#define AST_STATE_DOWN         0               
+/*! Channel is down, but reserved */
+#define AST_STATE_RESERVED     1               
+/*! Channel is off hook */
+#define AST_STATE_OFFHOOK      2               
+/*! Digits (or equivalent) have been dialed */
+#define AST_STATE_DIALING      3               
+/*! Line is ringing */
+#define AST_STATE_RING         4               
+/*! Remote end is ringing */
+#define AST_STATE_RINGING      5               
+/*! Line is up */
+#define AST_STATE_UP           6               
+/*! Line is busy */
+#define AST_STATE_BUSY         7               
 
 /* Bits 16-32 of state are reserved for flags */
-
-#define AST_STATE_MUTE         (1 << 16)       /* Do not transmit voice data */
-
-/* Request a channel of a given type, with data as optional information used
-   by the low level module */
+/*! Do not transmit voice data */
+#define AST_STATE_MUTE         (1 << 16)       
+
+//! Requests a channel
+/*! 
+ * \param type type of channel to request
+ * \param format requested channel format
+ * \param data data to pass to the channel requester
+ * Request a channel of a given type, with data as optional information used 
+ * by the low level module
+ * Returns an ast_channel on success, NULL on failure.
+ */
 struct ast_channel *ast_request(char *type, int format, void *data);
 
-/* Called by a channel module to register the kind of channels it supports.
-   It supplies a brief type, a longer, but still short description, and a
-   routine that creates a channel */
+//! Registers a channel
+/*! 
+ * \param type type of channel you are registering
+ * \param description short description of the channel
+ * \param capabilities a bit mask of the capabilities of the channel
+ * \param requester a function pointer that properly responds to a call.  See one of the channel drivers for details.
+ * Called by a channel module to register the kind of channels it supports.
+ * It supplies a brief type, a longer, but still short description, and a
+ * routine that creates a channel
+ * Returns 0 on success, -1 on failure.
+ */
 int ast_channel_register(char *type, char *description, int capabilities, 
                        struct ast_channel* (*requester)(char *type, int format, void *data));
 
-/* Unregister a channel class */
+//! Unregister a channel class
+/*
+ * \param type the character string that corresponds to the channel you wish to unregister
+ * Basically just unregisters the channel with the asterisk channel system
+ * No return value.
+ */
 void ast_channel_unregister(char *type);
 
-/* Hang up a channel -- chan is no longer valid after this call! */
+//! Hang up a channel 
+/*! 
+ * \param chan channel to hang up
+ * This function performs a hard hangup on a channel.  Unlike the soft-hangup, this function
+ * performs all stream stopping, etc, on the channel that needs to end.
+ * chan is no longer valid after this call.
+ * Returns 0 on success, -1 on failure.
+ */
 int ast_hangup(struct ast_channel *chan);
 
-/* Softly hangup up a channel -- call the protocol layer, but don't
-   destroy the channel structure (use this if you are trying to
-   safely hangup a channel managed by another thread. */
+//! Softly hangup up a channel
+/*! 
+ * \param chan channel to be soft-hung-up
+ * Call the protocol layer, but don't destroy the channel structure (use this if you are trying to
+ * safely hangup a channel managed by another thread.
+ * Returns 0 regardless
+ */
 int ast_softhangup(struct ast_channel *chan);
 
-/* Answer a ringing call */
+//! Check to see if a channel is needing hang up
+/*! 
+ * \param chan channel on which to check for hang up
+ * This function determines if the channel is being requested to be hung up.
+ * Returns 0 if not, or 1 if hang up is requested (including time-out).
+ */
+int ast_check_hangup(struct ast_channel *chan);
+
+//! Set when to hang a channel up
+/*! 
+ * \param chan channel on which to check for hang up
+ * \param offset offset in seconds from current time of when to hang up
+ * This function sets the absolute time out on a channel (when to hang up).
+ */
+void ast_channel_setwhentohangup(struct ast_channel *chan, time_t offset);
+
+//! Answer a ringing call
+/*!
+ * \param chan channel to answer
+ * This function answers a channel and handles all necessary call
+ * setup functions.
+ * Returns 0 on success, -1 on failure
+ */
 int ast_answer(struct ast_channel *chan);
 
-/* Place a call, take no longer than timeout ms.  Returns -1 on failure, 
+//! Make a call
+/*! 
+ * \param chan which channel to make the call on
+ * \param addr destination of the call
+ * \param timeout time to wait on for connect
+ * Place a call, take no longer than timeout ms.  Returns -1 on failure, 
    0 on not enough time (does not auto matically stop ringing), and  
-   the number of seconds the connect took otherwise.  */
+   the number of seconds the connect took otherwise.
+   Returns 0 on success, -1 on failure
+   */
 int ast_call(struct ast_channel *chan, char *addr, int timeout);
 
-/* Indicate a condition such as AST_CONTROL_BUSY, AST_CONTROL_RINGING, or AST_CONTROL_CONGESTION on a channel */
+//! Indicates condition of channel
+/*! 
+ * \param chan channel to change the indication
+ * \param condition which condition to indicate on the channel
+ * Indicate a condition such as AST_CONTROL_BUSY, AST_CONTROL_RINGING, or AST_CONTROL_CONGESTION on a channel
+ * Returns 0 on success, -1 on failure
+ */
 int ast_indicate(struct ast_channel *chan, int condition);
 
 /* Misc stuff */
 
-/* Wait for input on a channel for a given # of milliseconds (<0 for indefinite).  
+//! Wait for input on a channel
+/*! 
+ * \param chan channel to wait on
+ * \param ms length of time to wait on the channel
+ * Wait for input on a channel for a given # of milliseconds (<0 for indefinite). 
   Returns < 0 on  failure, 0 if nothing ever arrived, and the # of ms remaining otherwise */
 int ast_waitfor(struct ast_channel *chan, int ms);
 
-/* Big momma function here.  Wait for activity on any of the n channels, or any of the nfds
+//! Waits for activity on a group of channels
+/*! 
+ * \param chan an array of pointers to channels
+ * \param n number of channels that are to be waited upon
+ * \param fds an array of fds to wait upon
+ * \param nfds the number of fds to wait upon
+ * \param exception exception flag
+ * \param outfd fd that had activity on it
+ * \param ms how long the wait was
+ * Big momma function here.  Wait for activity on any of the n channels, or any of the nfds
    file descriptors.  Returns the channel with activity, or NULL on error or if an FD
    came first.  If the FD came first, it will be returned in outfd, otherwise, outfd
    will be -1 */
 struct ast_channel *ast_waitfor_nandfds(struct ast_channel **chan, int n, int *fds, int nfds, int *exception, int *outfd, int *ms);
 
-/* Wait for input on an array of channels for a given # of milliseconds. Return channel
+//! Waits for input on a group of channels
+/*! Wait for input on an array of channels for a given # of milliseconds. Return channel
    with activity, or NULL if none has activity.  time "ms" is modified in-place, if applicable */
-
 struct ast_channel *ast_waitfor_n(struct ast_channel **chan, int n, int *ms);
 
-/* This version works on fd's only.  Be careful with it. */
+//! Waits for input on an fd
+/*! This version works on fd's only.  Be careful with it. */
 int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception);
 
-/* Read a frame.  Returns a frame, or NULL on error.  If it returns NULL, you
+
+//! Reads a frame
+/*! 
+ * \param chan channel to read a frame from
+ * Read a frame.  Returns a frame, or NULL on error.  If it returns NULL, you
    best just stop reading frames and assume the channel has been
    disconnected. */
 struct ast_frame *ast_read(struct ast_channel *chan);
 
-/* Write a frame to a channel */
+//! Write a frame to a channel
+/*!
+ * \param chan destination channel of the frame
+ * \param frame frame that will be written
+ * This function writes the given frame to the indicated channel.
+ * It returns 0 on success, -1 on failure.
+ */
 int ast_write(struct ast_channel *chan, struct ast_frame *frame);
 
-/* Set read format for channelto whichever component of "format" is best. */
+//! Sets read format on channel chan
+/*! 
+ * \param chan channel to change
+ * \param format format to change to
+ * Set read format for channel to whichever component of "format" is best. 
+ * Returns 0 on success, -1 on failure
+ */
 int ast_set_read_format(struct ast_channel *chan, int format);
 
-/* Set write format for channel to whichever compoent of "format" is best. */
+//! Sets write format on channel chan
+/*! 
+ * \param chan channel to change
+ * \param format new format for writing
+ * Set write format for channel to whichever compoent of "format" is best. 
+ * Returns 0 on success, -1 on failure
+ */
 int ast_set_write_format(struct ast_channel *chan, int format);
 
-/* Write text to a display on a channel */
+//! Sends text to a channel
+/*! 
+ * \param chan channel to act upon
+ * \param text string of text to send on the channel
+ * Write text to a display on a channel
+ * Returns 0 on success, -1 on failure
+ */
 int ast_sendtext(struct ast_channel *chan, char *text);
 
-/* Browse the channels currently in use */
+//! Receives a text character from a channel
+/*! 
+ * \param chan channel to act upon
+ * \param timeout timeout in milliseconds (0 for infinite wait)
+ * Read a char of text from a channel
+ * Returns 0 on success, -1 on failure
+ */
+int ast_recvchar(struct ast_channel *chan, int timeout);
+
+//! Browse channels in use
+/*! 
+ * \param prev where you want to start in the channel list
+ * Browse the channels currently in use 
+ * Returns the next channel in the list, NULL on end.
+ */
 struct ast_channel *ast_channel_walk(struct ast_channel *prev);
 
-/* Wait for a digit.  Returns <0 on error, 0 on no entry, and the digit on success. */
+//! Waits for a digit
+/*! 
+ * \param c channel to wait for a digit on
+ * \param ms how many milliseconds to wait
+ * Wait for a digit.  Returns <0 on error, 0 on no entry, and the digit on success. */
 char ast_waitfordigit(struct ast_channel *c, int ms);
 
-/* Read in a digit string "s", max length "len", maximum timeout between 
+//! Reads multiple digits
+/*! 
+ * \param c channel to read from
+ * \param s string to read in to.  Must be at least the size of your length
+ * \param len how many digits to read
+ * \param timeout how long to timeout between digits
+ * \param rtimeout timeout to wait on the first digit
+ * \param enders digits to end the string
+ * Read in a digit string "s", max length "len", maximum timeout between 
    digits "timeout" (-1 for none), terminated by anything in "enders".  Give them rtimeout
    for the first digit.  Returns 0 on normal return, or 1 on a timeout.  In the case of
    a timeout, any digits that were read before the timeout will still be available in s.  */
 int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders);
 
-#define AST_BRIDGE_DTMF_CHANNEL_0              (1 << 0)                /* Report DTMF on channel 0 */
-#define AST_BRIDGE_DTMF_CHANNEL_1              (1 << 1)                /* Report DTMF on channel 1 */
-#define AST_BRIDGE_REC_CHANNEL_0               (1 << 2)                /* Return all voice frames on channel 0 */
-#define AST_BRIDGE_REC_CHANNEL_1               (1 << 3)                /* Return all voice frames on channel 1 */
-#define AST_BRIDGE_IGNORE_SIGS                 (1 << 4)                /* Ignore all signal frames except NULL */
-
-
-/* Set two channels to compatible formats -- call before ast_channel_bridge in general .  Returns 0 on success
+/*! Report DTMF on channel 0 */
+#define AST_BRIDGE_DTMF_CHANNEL_0              (1 << 0)                
+/*! Report DTMF on channel 1 */
+#define AST_BRIDGE_DTMF_CHANNEL_1              (1 << 1)                
+/*! Return all voice frames on channel 0 */
+#define AST_BRIDGE_REC_CHANNEL_0               (1 << 2)                
+/*! Return all voice frames on channel 1 */
+#define AST_BRIDGE_REC_CHANNEL_1               (1 << 3)                
+/*! Ignore all signal frames except NULL */
+#define AST_BRIDGE_IGNORE_SIGS                 (1 << 4)                
+
+
+//! Makes two channel formats compatible
+/*! 
+ * \param c0 first channel to make compatible
+ * \param c1 other channel to make compatible
+ * Set two channels to compatible formats -- call before ast_channel_bridge in general .  Returns 0 on success
    and -1 if it could not be done */
 int ast_channel_make_compatible(struct ast_channel *c0, struct ast_channel *c1);
 
-/* Bridge two channels (c0 and c1) together.  If an important frame occurs, we return that frame in
+//! Bridge two channels together
+/*! 
+ * \param c0 first channel to bridge
+ * \param c1 second channel to bridge
+ * \param flags for the channels
+ * \param fo destination frame(?)
+ * \param rc destination channel(?)
+ * Bridge two channels (c0 and c1) together.  If an important frame occurs, we return that frame in
    *rf (remember, it could be NULL) and which channel (0 or 1) in rc */
 int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc);
 
-/* This is a very strange and freaky function used primarily for transfer.  Suppose that
+//! Weird function made for call transfers
+/*! 
+ * \param original channel to make a copy of
+ * \param clone copy of the original channel
+ * This is a very strange and freaky function used primarily for transfer.  Suppose that
    "original" and "clone" are two channels in random situations.  This function takes
    the guts out of "clone" and puts them into the "original" channel, then alerts the
    channel driver of the change, asking it to fixup any private information (like the
@@ -271,7 +498,13 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
    channel is hung up.  */
 int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone);
 
-/* Give a name to a state */
+//! Gives the string form of a given state
+/*! 
+ * \param state state to get the name of
+ * Give a name to a state 
+ * Pretty self explanatory.
+ * Returns the text form of the binary state given
+ */
 char *ast_state2str(int state);
 
 /* Options: Some low-level drivers may implement "options" allowing fine tuning of the
@@ -279,27 +512,45 @@ char *ast_state2str(int state);
    none or a subset of those features, and you should not count on this if you want your
    asterisk application to be portable.  They're mainly useful for tweaking performance */
 
-/* Set an option on a channel (see frame.h), optionally blocking awaiting the reply */
+//! Sets an option on a channel
+/*! 
+ * \param channel channel to set options on
+ * \param option option to change
+ * \param data data specific to option
+ * \param datalen length of the data
+ * \param block blocking or not
+ * Set an option on a channel (see frame.h), optionally blocking awaiting the reply 
+ * Returns 0 on success and -1 on failure
+ */
 int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block);
 
-/* Query the value of an option, optionally blocking until a reply is received */
+//! Checks the value of an option
+/*! 
+ * Query the value of an option, optionally blocking until a reply is received
+ * Works similarly to setoption except only reads the options.
+ */
 struct ast_frame *ast_channel_queryoption(struct ast_channel *channel, int option, void *data, int *datalen, int block);
 
-/* Returns 0 if channel does not support HTML or non-zero if it does */
+//! Checks for HTML support on a channel
+/*! Returns 0 if channel does not support HTML or non-zero if it does */
 int ast_channel_supports_html(struct ast_channel *channel);
 
-/* Send HTML or URL on link.  Returns 0 on success or -1 on failure */
+//! Sends HTML on given channel
+/*! Send HTML or URL on link.  Returns 0 on success or -1 on failure */
 int ast_channel_sendhtml(struct ast_channel *channel, int subclass, char *data, int datalen);
 
-/* Send URL on link.  Returns 0 on success or -1 on failure */
+//! Sends a URL on a given link
+/*! Send URL on link.  Returns 0 on success or -1 on failure */
 int ast_channel_sendurl(struct ast_channel *channel, char *url);
 
-/* Defer DTMF so that you only read things like hangups and audio.  Returns
+//! Defers DTMF
+/*! Defer DTMF so that you only read things like hangups and audio.  Returns
    non-zero if channel was already DTMF-deferred or 0 if channel is just now
    being DTMF-deferred */
 int ast_channel_defer_dtmf(struct ast_channel *chan);
 
-/* Undo defer.  ast_read will return any dtmf characters that were queued */
+//! Undeos a defer
+/*! Undo defer.  ast_read will return any dtmf characters that were queued */
 void ast_channel_undefer_dtmf(struct ast_channel *chan);
 
 #ifdef DO_CRASH