Index: zaptel-base.c =================================================================== --- zaptel-base.c (revision 854) +++ zaptel-base.c (working copy) @@ -745,6 +745,20 @@ unsigned char *newbuf, *oldbuf; unsigned long flags; int x; + + /* Allocate history buffer, or not. This probably shouldn't + * be here, but it's convenient */ + if(!j) + { + if(ss->history) kfree(ss->history); + ss->history = NULL; + } + else + { + if(!ss->history) ss->history=kmalloc(ZT_HISTORY_BUF_LEN, GFP_KERNEL); + } + ss->historypos=0; + /* Check numbufs */ if (numbufs < 2) numbufs = 2; @@ -3445,6 +3459,8 @@ unsigned long flags, flagso; int i, j, k, rv; int ret, c; + int k1, k2; + struct zt_history hist; if (!chan) return -EINVAL; @@ -3923,6 +3939,29 @@ } } break; + case ZT_GET_HISTORY: + if (copy_from_user(&hist,(struct zt_history *) data,sizeof(hist))) + return -EIO; + + if (!(chan->flags & ZT_FLAG_AUDIO)) return (-EINVAL); + if (!chan->history) return -EINVAL; + j=hist.len; + k1=ZT_HISTORY_BUF_LEN-chan->historypos; + k2=chan->historypos; + if(j>0 && k1>0) + { + if (copy_to_user(hist.buf,chan->history+chan->historypos,min(j,k1))) + return -EIO; + j-=min(j,k1); + } + if(j>0 && k2>0) + { + if (copy_to_user(hist.buf+k1,chan->history,min(j,k2))) + return -EIO; + j-=min(j,k2); + } + /* Probably should assert j==0 here */ + break; default: /* Check for common ioctl's and private ones */ rv = zt_common_ioctl(inode, file, cmd, data, unit); @@ -5587,6 +5626,15 @@ memcpy(ms->putlin, putlin, ZT_CHUNKSIZE * sizeof(short)); memcpy(ms->putraw, rxb, ZT_CHUNKSIZE); } + + /* Store in the history buffer */ + if(ms->history) + { + memcpy(ms->history+ms->historypos,rxb,ZT_CHUNKSIZE); + ms->historypos+=ZT_CHUNKSIZE; + if(ms->historypos >= ZT_HISTORY_BUF_LEN) + ms->historypos=0; + } /* Take the rxc, twiddle it for conferencing if appropriate and put it back */ Index: zaptel.h =================================================================== --- zaptel.h (revision 854) +++ zaptel.h (working copy) @@ -143,6 +143,8 @@ #define ZT_MAX_NUM_BUFS 32 #define ZT_MAX_BUF_SPACE 32768 +#define ZT_HISTORY_BUF_LEN 16384 /* Count of ulaw samples */ + #define ZT_DEFAULT_BLOCKSIZE 1024 #define ZT_DEFAULT_MTR_MRU 2048 @@ -289,6 +291,11 @@ int reserved[4]; /* Reserved for future expansion -- always set to 0 */ } ZT_DIAL_PARAMS; +typedef struct zt_history +{ + unsigned char *buf; /* Sample buffer */ + int len; /* Length of buffer, in bytes */ +} ZT_HISTORY; typedef struct zt_dynamic_span { char driver[20]; /* Which low-level driver to use */ @@ -604,6 +611,11 @@ #define ZT_TIMERPONG _IOW (ZT_CODE, 53, int) /* + * Return history buffer + */ +#define ZT_GET_HISTORY _IOR(ZT_CODE, 66, struct zt_history) + +/* * Set/get signalling freeze */ #define ZT_SIGFREEZE _IOW (ZT_CODE, 54, int) @@ -1039,6 +1051,10 @@ int blocksize; /* Block size */ + + u_char *history; /* History buffer, for pre-ring caller ID (ZT_HISTORY_BUF_LEN) */ + u_short historypos; /* Current position within buffer */ + int eventinidx; /* out index in event buf (circular) */ int eventoutidx; /* in index in event buf (circular) */ unsigned int eventbuf[ZT_MAX_EVENTSIZE]; /* event circ. buffer */