Commit 6f521bb5 authored by Harald Welte's avatar Harald Welte

Introduce ioctl() for simulating alarms under userspace control

For automatic testing scenarios, it is very useful to be able to
artificially create line alarms.  This allows testing of the whole
stack through DAHDI itself, DAHDI-interfaces in applications and
actual applications.

It introduces a new DAHDI_SIMULATE_ALARM ioctl() whcih has to be
issued on /dev/dahdi/ctl and which can be used to set or remove
any simulated alarms on the given span.
parent 115f487f
......@@ -5591,6 +5591,7 @@ dahdi_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long data)
return dahdi_ioctl_maint(data);
case DAHDI_DYNAMIC_CREATE:
case DAHDI_DYNAMIC_DESTROY:
case DAHDI_SIMULATE_ALARM:
return dahdi_ioctl_dynamic(cmd, data);
case DAHDI_EC_LICENSE_CHALLENGE:
case DAHDI_EC_LICENSE_RESPONSE:
......
......@@ -366,7 +366,7 @@ void dahdi_dynamic_receive(struct dahdi_span *span, unsigned char *msg, int msgl
rcu_read_unlock();
/* Check for Yellow alarm */
newalarm = span->alarms & ~(DAHDI_ALARM_YELLOW | DAHDI_ALARM_RED);
newalarm = dtd->simulated_alarms | (span->alarms & ~(DAHDI_ALARM_YELLOW | DAHDI_ALARM_RED));
if (sflags & DAHDI_DYNAMIC_FLAG_YELLOW_ALARM)
newalarm |= DAHDI_ALARM_YELLOW;
......@@ -745,9 +745,31 @@ static void dahdi_dynamic_flush_tasklet(unsigned long data)
}
#endif
static int simulate_alarm(const struct dahdi_simulate_alarm *dsa)
{
struct dahdi_dynamic *d;
rcu_read_lock();
list_for_each_entry_rcu(d, &dspan_list, list) {
if (d->span.spanno == dsa->spanno) {
/* mask off old simulated alarms */
d->span.alarms &= ~d->simulated_alarms;
d->simulated_alarms = dsa->alarms;
/* mask in new simulated alarms */
d->span.alarms |= d->simulated_alarms;
dahdi_alarm_notify(&d->span);
return 0;
}
}
return -ENODEV;
}
static int dahdi_dynamic_ioctl(unsigned int cmd, unsigned long data)
{
struct dahdi_dynamic_span dds;
struct dahdi_simulate_alarm dsa;
int res;
switch(cmd) {
case DAHDI_DYNAMIC_CREATE:
......@@ -771,6 +793,11 @@ static int dahdi_dynamic_ioctl(unsigned int cmd, unsigned long data)
if (debug)
printk(KERN_DEBUG "Dynamic Destroy\n");
return destroy_dynamic(&dds);
case DAHDI_SIMULATE_ALARM:
if (copy_from_user(&dsa, (__user const void *)data,
sizeof(dsa)))
return -EFAULT;
return simulate_alarm(&dsa);
}
return -ENOTTY;
......@@ -839,7 +866,7 @@ static void check_for_red_alarm(TIMER_DATA_TYPE unused)
rcu_read_lock();
list_for_each_entry_rcu(d, &dspan_list, list) {
newalarm = d->span.alarms & ~DAHDI_ALARM_RED;
newalarm = d->simulated_alarms | (d->span.alarms & ~DAHDI_ALARM_RED);
/* If nothing received for a second, consider that RED ALARM */
if ((jiffies - d->rxjif) > 1 * HZ) {
newalarm |= DAHDI_ALARM_RED;
......
......@@ -1068,6 +1068,7 @@ struct dahdi_dynamic {
int master;
unsigned char *msgbuf;
struct device *dev;
int simulated_alarms;
struct list_head list;
};
......
......@@ -1025,6 +1025,14 @@ struct dahdi_dynamic_span {
*/
#define DAHDI_DYNAMIC_DESTROY _IOW(DAHDI_CODE, 81, struct dahdi_dynamic_span)
struct dahdi_simulate_alarm {
int spanno;
int alarms;
};
/* simulate alarms on a dynamic span */
#define DAHDI_SIMULATE_ALARM _IOW(DAHDI_CODE, 82, struct dahdi_simulate_alarm)
/*
* Set the HW gain for a device
*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment