From a4feafc124da614f8352b353ada39824d79ac5a3 Mon Sep 17 00:00:00 2001 From: Shaun Ruffell Date: Mon, 21 Jan 2013 12:57:37 -0600 Subject: [PATCH] dahdi: Restore DAHDI_CONFLINK functionality as compile time option. This is mostly a revert of commit r9463. If you need to use DAHDI_CONFLINK ioctl, make sure to define CONFIG_DAHDI_CONFLINK in include/dahdi/dahdi_config.h. Apparently there were some users of CONFLINK out there still. It's a compile time option now since most users won't need to run the test for conflinks in the hot-path that is the process_masterspan function. Signed-off-by: Shaun Ruffell Tested-by: Ted Gerold --- drivers/dahdi/dahdi-base.c | 161 ++++++++++++++++++++++++++++++++++- include/dahdi/dahdi_config.h | 6 ++ include/dahdi/user.h | 5 ++ 3 files changed, 171 insertions(+), 1 deletion(-) diff --git a/drivers/dahdi/dahdi-base.c b/drivers/dahdi/dahdi-base.c index e8275b6..768855a 100644 --- a/drivers/dahdi/dahdi-base.c +++ b/drivers/dahdi/dahdi-base.c @@ -176,6 +176,17 @@ static sumtype *conf_sums_prev; static struct dahdi_span *master; struct file_operations *dahdi_transcode_fops = NULL; + +#ifdef CONFIG_DAHDI_CONFLINK +static struct { + int src; /* source conf number */ + int dst; /* dst conf number */ +} conf_links[DAHDI_MAX_CONF + 1]; + +static int maxlinks; + +#endif + #ifdef CONFIG_DAHDI_CORE_TIMER static struct core_timer { @@ -4507,6 +4518,104 @@ static int dahdi_ioctl_spanstat_v1(struct file *file, unsigned long data) return ret; } +#ifdef CONFIG_DAHDI_CONFLINK +static void recalc_maxlinks(void) +{ + int x; + + for (x = DAHDI_MAX_CONF - 1; x > 0; x--) { + if (conf_links[x].src || conf_links[x].dst) { + maxlinks = x + 1; + return; + } + } + + maxlinks = 0; +} + +static int dahdi_ioctl_conflink(struct file *file, unsigned long data) +{ + struct dahdi_chan *chan; + struct dahdi_confinfo conf; + unsigned long flags; + int res = 0; + int i; + + chan = chan_from_file(file); + if (!chan) + return -EINVAL; + if (!(chan->flags & DAHDI_FLAG_AUDIO)) + return -EINVAL; + if (copy_from_user(&conf, (void __user *)data, sizeof(conf))) + return -EFAULT; + /* check sanity of arguments */ + if ((conf.chan < 0) || (conf.chan > DAHDI_MAX_CONF)) + return -EINVAL; + if ((conf.confno < 0) || (conf.confno > DAHDI_MAX_CONF)) + return -EINVAL; + /* cant listen to self!! */ + if (conf.chan && (conf.chan == conf.confno)) + return -EINVAL; + + spin_lock_irqsave(&chan_lock, flags); + spin_lock(&chan->lock); + + /* if to clear all links */ + if ((!conf.chan) && (!conf.confno)) { + /* clear all the links */ + memset(conf_links, 0, sizeof(conf_links)); + recalc_maxlinks(); + spin_unlock(&chan->lock); + spin_unlock_irqrestore(&chan_lock, flags); + return 0; + } + /* look for already existant specified combination */ + for (i = 1; i <= DAHDI_MAX_CONF; i++) { + /* if found, exit */ + if ((conf_links[i].src == conf.chan) && + (conf_links[i].dst == conf.confno)) + break; + } + if (i <= DAHDI_MAX_CONF) { /* if found */ + if (!conf.confmode) { /* if to remove link */ + conf_links[i].src = 0; + conf_links[i].dst = 0; + } else { /* if to add and already there, error */ + res = -EEXIST; + } + } else { /* if not found */ + if (conf.confmode) { /* if to add link */ + /* look for empty location */ + for (i = 1; i <= DAHDI_MAX_CONF; i++) { + /* if empty, exit loop */ + if ((!conf_links[i].src) && + (!conf_links[i].dst)) + break; + } + /* if empty spot found */ + if (i <= DAHDI_MAX_CONF) { + conf_links[i].src = conf.chan; + conf_links[i].dst = conf.confno; + } else { /* if no empties -- error */ + res = -ENOSPC; + } + } else { /* if to remove, and not found -- error */ + res = -ENOENT; + } + } + recalc_maxlinks(); + spin_unlock(&chan->lock); + spin_unlock_irqrestore(&chan_lock, flags); + return res; +} +#else +static int dahdi_ioctl_conflink(struct file *file, unsigned long data) +{ + return -ENOSYS; +} +#endif + + static int dahdi_common_ioctl(struct file *file, unsigned int cmd, unsigned long data) { @@ -4535,6 +4644,10 @@ static int dahdi_common_ioctl(struct file *file, unsigned int cmd, case DAHDI_CHANDIAG_V1: /* Intentional drop through. */ case DAHDI_CHANDIAG: return dahdi_ioctl_chandiag(file, data); + + case DAHDI_CONFLINK: + return dahdi_ioctl_conflink(file, data); + default: return -ENOTTY; } @@ -5607,10 +5720,10 @@ static int dahdi_ioctl_confdiag(struct file *file, unsigned long data) for (i = ((j) ? j : 1); i <= ((j) ? j : DAHDI_MAX_CONF); i++) { struct dahdi_span *s; struct pseudo_chan *pseudo; + int k; c = 0; spin_lock_irqsave(&chan_lock, flags); list_for_each_entry(s, &span_list, spans_node) { - int k; for (k = 0; k < s->channels; k++) { chan = s->chans[k]; if (chan->confna != i) @@ -5632,6 +5745,29 @@ static int dahdi_ioctl_confdiag(struct file *file, unsigned long data) module_printk(KERN_NOTICE, "chan %d, mode %x\n", pseudo->chan.channo, pseudo->chan.confmode); } + +#ifdef CONFIG_DAHDI_CONFLINK + { + int rv; + rv = 0; + for (k = 1; k <= DAHDI_MAX_CONF; k++) { + if (conf_links[k].dst == i) { + if (!c) { + c = 1; + module_printk(KERN_NOTICE, + "Conf #%d:\n", i); + } + if (!rv) { + rv = 1; + module_printk(KERN_NOTICE, + "Snooping on:\n"); + } + module_printk(KERN_NOTICE, "conf %d\n", + conf_links[k].src); + } + } + } +#endif spin_unlock_irqrestore(&chan_lock, flags); if (c) module_printk(KERN_NOTICE, "\n"); @@ -9714,6 +9850,29 @@ static void _process_masterspan(void) spin_unlock(&pseudo->chan.lock); } +#ifdef CONFIG_DAHDI_CONFLINK + if (maxlinks) { + int z; + int y; +#ifdef CONFIG_DAHDI_MMX + dahdi_kernel_fpu_begin(); +#endif + /* process all the conf links */ + for (x = 1; x <= maxlinks; x++) { + /* if we have a destination conf */ + z = confalias[conf_links[x].dst]; + if (z) { + y = confalias[conf_links[x].src]; + if (y) + ACSS(conf_sums[z], conf_sums[y]); + } + } +#ifdef CONFIG_DAHDI_MMX + dahdi_kernel_fpu_end(); +#endif + } +#endif /* CONFIG_DAHDI_CONFLINK */ + /* do all the pseudo/conferenced channel transmits (putbuf's) */ list_for_each_entry(pseudo, &pseudo_chans, node) { pseudo_rx_audio(&pseudo->chan); diff --git a/include/dahdi/dahdi_config.h b/include/dahdi/dahdi_config.h index 0957689..6af9953 100644 --- a/include/dahdi/dahdi_config.h +++ b/include/dahdi/dahdi_config.h @@ -190,4 +190,10 @@ */ /* #define CONFIG_DAHDI_MIRROR */ +/* + * Adds support for conference links. There are some non-Asterisk users of this + * functionality. + */ +/* #define CONFIG_DAHDI_CONFLINK */ + #endif diff --git a/include/dahdi/user.h b/include/dahdi/user.h index 5f2d192..68e72e0 100644 --- a/include/dahdi/user.h +++ b/include/dahdi/user.h @@ -636,6 +636,11 @@ struct dahdi_confinfo { #define DAHDI_SETCONF_V1 _IOW(DAHDI_CODE, 12, struct dahdi_confinfo) #define DAHDI_SETCONF _IOWR(DAHDI_CODE, 13, struct dahdi_confinfo) +/* + * Setup or Remove Conference Link + */ +#define DAHDI_CONFLINK _IOW(DAHDI_CODE, 14, struct dahdi_confinfo) + /* * Display Conference Diagnostic Information on Console */