summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xMakefile10
-rwxr-xr-xzaptel.c144
-rwxr-xr-xzaptel.h10
3 files changed, 162 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index 74f8a70..19cdc5f 100755
--- a/Makefile
+++ b/Makefile
@@ -88,7 +88,7 @@ all: $(MODULES) ztcfg torisatool makefw ztmonitor ztspeed $(ZTTOOL)
devel: tor2ee
-tests: patgen pattest patlooptest hdlcstress hdlctest hdlcgen hdlcverify
+tests: patgen pattest patlooptest hdlcstress hdlctest hdlcgen hdlcverify timertest
tor2.o: tor2.c tor2-hw.h tor.h tor2fw.h zaptel.h
gcc $(KFLAGS) -c tor2.c
@@ -205,11 +205,17 @@ devices:
rm -f $(INSTALL_PREFIX)/dev/zap/ctl
rm -f $(INSTALL_PREFIX)/dev/zap/channel
rm -f $(INSTALL_PREFIX)/dev/zap/pseudo
+ rm -f $(INSTALL_PREFIX)/dev/zap/timer
+ rm -f $(INSTALL_PREFIX)/dev/zap/253
+ rm -f $(INSTALL_PREFIX)/dev/zap/252
+ rm -f $(INSTALL_PREFIX)/dev/zap/251
+ rm -f $(INSTALL_PREFIX)/dev/zap/250
mknod $(INSTALL_PREFIX)/dev/zap/ctl c 196 0
+ mknod $(INSTALL_PREFIX)/dev/zap/timer c 196 253
mknod $(INSTALL_PREFIX)/dev/zap/channel c 196 254
mknod $(INSTALL_PREFIX)/dev/zap/pseudo c 196 255
N=1; \
- while [ $$N -lt 253 ]; do \
+ while [ $$N -lt 250 ]; do \
rm -f $(INSTALL_PREFIX)/dev/zap/$$N; \
mknod $(INSTALL_PREFIX)/dev/zap/$$N c 196 $$N; \
N=$$[$$N+1]; \
diff --git a/zaptel.c b/zaptel.c
index e8ba8d1..df42b14 100755
--- a/zaptel.c
+++ b/zaptel.c
@@ -263,6 +263,16 @@ static inline void zt_kernel_fpu_begin(void)
}
#endif
+static struct zt_timer {
+ int ms; /* Countdown */
+ int pos; /* Position */
+ int tripped; /* Whether we're tripped */
+ struct zt_timer *next; /* Linked list */
+ wait_queue_head_t sel;
+} *zaptimers = NULL;
+
+static spinlock_t zaptimerlock = SPIN_LOCK_UNLOCKED;
+
struct zt_zone {
char name[40]; /* Informational, only */
int ringcadence[ZT_MAX_CADENCE];
@@ -1840,7 +1850,56 @@ static int initialize_channel(struct zt_chan *chan)
return 0;
}
+static int zt_timing_open(struct inode *inode, struct file *file)
+{
+ struct zt_timer *t;
+ long flags;
+ t = kmalloc(sizeof(struct zt_timer), GFP_KERNEL);
+ if (!t)
+ return -ENOMEM;
+ /* Allocate a new timer */
+ memset(t, 0, sizeof(struct zt_timer));
+ init_waitqueue_head(&t->sel);
+ file->private_data = t;
+ MOD_INC_USE_COUNT;
+ spin_lock_irqsave(&zaptimerlock, flags);
+ t->next = zaptimers;
+ zaptimers = t;
+ spin_unlock_irqrestore(&zaptimerlock, flags);
+ return 0;
+}
+static int zt_timer_release(struct inode *inode, struct file *file)
+{
+ struct zt_timer *t, *cur, *prev;
+ long flags;
+ t = file->private_data;
+ if (t) {
+ spin_lock_irqsave(&zaptimerlock, flags);
+ prev = NULL;
+ cur = zaptimers;
+ while(cur) {
+ if (t == cur)
+ break;
+ prev = cur;
+ cur = cur->next;
+ }
+ if (cur) {
+ if (prev)
+ prev->next = cur->next;
+ else
+ zaptimers = cur->next;
+ }
+ spin_unlock_irqrestore(&zaptimerlock, flags);
+ if (!cur) {
+ printk("Zap Timer: Not on list??\n");
+ return 0;
+ }
+ kfree(t);
+ MOD_DEC_USE_COUNT;
+ }
+ return 0;
+}
static int zt_specchan_open(struct inode *inode, struct file *file, int unit, int inc)
{
@@ -1922,6 +1981,8 @@ static int zt_open(struct inode *inode, struct file *file)
/* Minor 0: Special "control" descriptor */
if (!unit)
return zt_ctl_open(inode, file);
+ if (unit == 253)
+ return zt_timing_open(inode, file);
if (unit == 254)
return zt_chan_open(inode, file);
if (unit == 255) {
@@ -1946,6 +2007,9 @@ static ssize_t zt_read(struct file *file, char *usrbuf, size_t count, loff_t *pp
return -EINVAL;
}
+ if (unit == 253)
+ return -EINVAL;
+
if (unit == 254) {
chan = file->private_data;
if (!chan)
@@ -1976,6 +2040,8 @@ static ssize_t zt_write(struct file *file, const char *usrbuf, size_t count, lof
return -EINVAL;
if (count < 0)
return -EINVAL;
+ if (unit == 253)
+ return -EINVAL;
if (unit == 254) {
chan = file->private_data;
if (!chan)
@@ -2188,6 +2254,9 @@ static int zt_release(struct inode *inode, struct file *file)
if (!unit)
return zt_ctl_release(inode, file);
+ if (unit == 253) {
+ return zt_timer_release(inode, file);
+ }
if (unit == 254) {
chan = file->private_data;
if (!chan)
@@ -2254,6 +2323,32 @@ void zt_alarm_notify(struct zt_span *span)
return -ENXIO; \
} while(0)
+static int zt_timer_ioctl(struct inode *node, struct file *file, unsigned int cmd, unsigned long data, struct zt_timer *timer)
+{
+ int j;
+ unsigned long flags;
+ switch(cmd) {
+ case ZT_TIMERCONFIG:
+ get_user(j, (int *)data);
+ if (j < 0)
+ j = 0;
+ spin_lock_irqsave(&zaptimerlock, flags);
+ timer->ms = timer->pos = j;
+ spin_unlock_irqrestore(&zaptimerlock, flags);
+ break;
+ case ZT_TIMERACK:
+ get_user(j, (int *)data);
+ spin_lock_irqsave(&zaptimerlock, flags);
+ if ((j < 1) || (j > timer->tripped))
+ j = timer->tripped;
+ timer->tripped -= j;
+ spin_unlock_irqrestore(&zaptimerlock, flags);
+ break;
+ default:
+ return -ENOTTY;
+ }
+ return 0;
+}
static int zt_common_ioctl(struct inode *node, struct file *file, unsigned int cmd, unsigned long data, int unit)
{
struct zt_gains gain;
@@ -3597,9 +3692,17 @@ static int zt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
{
int unit = UNIT(file);
struct zt_chan *chan;
+ struct zt_timer *timer;
if (!unit)
return zt_ctl_ioctl(inode, file, cmd, data);
+ if (unit == 253) {
+ timer = file->private_data;
+ if (timer)
+ return zt_timer_ioctl(inode, file, cmd, data, timer);
+ else
+ return -EINVAL;
+ }
if (unit == 254) {
chan = file->private_data;
if (chan)
@@ -4977,6 +5080,41 @@ out in the later versions, and is put back now. */
}
}
+static void process_timers(void)
+{
+ long flags;
+ struct zt_timer *cur;
+ spin_lock_irqsave(&zaptimerlock, flags);
+ cur = zaptimers;
+ while(cur) {
+ if (cur->ms) {
+ cur->pos -= ZT_CHUNKSIZE;
+ if (cur->pos <= 0) {
+ cur->tripped++;
+ cur->pos = cur->ms;
+ wake_up_interruptible(&cur->sel);
+ }
+ }
+ cur = cur->next;
+ }
+ spin_unlock_irqrestore(&zaptimerlock, flags);
+}
+
+static unsigned int zt_timer_poll(struct file *file, struct poll_table_struct *wait_table)
+{
+ struct zt_timer *timer = file->private_data;
+ long flags;
+ int ret = 0;
+ if (timer) {
+ poll_wait(file, &timer->sel, wait_table);
+ spin_lock_irqsave(&zaptimerlock, flags);
+ if (timer->tripped)
+ ret |= POLLPRI;
+ spin_unlock_irqrestore(&zaptimerlock, flags);
+ } else
+ ret = -EINVAL;
+ return ret;
+}
/* device poll routine */
static unsigned int
@@ -5017,6 +5155,10 @@ static unsigned int zt_poll(struct file *file, struct poll_table_struct *wait_ta
if (!unit)
return -EINVAL;
+
+ if (unit == 253)
+ return zt_timer_poll(file, wait_table);
+
if (unit == 254) {
chan = file->private_data;
if (!chan)
@@ -5262,6 +5404,8 @@ int zt_receive(struct zt_span *span)
}
if (span == master) {
+ /* Process any timers */
+ process_timers();
/* If we have dynamic stuff, call the ioctl with 0,0 parameters to
make it run */
if (zt_dynamic_ioctl)
diff --git a/zaptel.h b/zaptel.h
index b053cbe..4c32376 100755
--- a/zaptel.h
+++ b/zaptel.h
@@ -524,6 +524,16 @@ char dialstr[ZT_MAX_DTMF_BUF];
#define ZT_SFCONFIG _IOW (ZT_CODE, 46, struct zt_sfconfig)
/*
+ * Set timer expiration (in samples)
+ */
+#define ZT_TIMERCONFIG _IOW (ZT_CODE, 47, int)
+
+/*
+ * Acknowledge timer expiration (number to acknowledge, or -1 for all)
+ */
+#define ZT_TIMERACK _IOW (ZT_CODE, 48, int)
+
+/*
* 60-80 are reserved for private drivers
* 80-85 are reserved for dynamic span stuff
*/