summaryrefslogtreecommitdiff
path: root/kernel/zttranscode.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/zttranscode.c')
-rw-r--r--kernel/zttranscode.c564
1 files changed, 269 insertions, 295 deletions
diff --git a/kernel/zttranscode.c b/kernel/zttranscode.c
index e44895b..23a5dc8 100644
--- a/kernel/zttranscode.c
+++ b/kernel/zttranscode.c
@@ -3,7 +3,7 @@
*
* Written by Mark Spencer <markster@digium.com>
*
- * Copyright (C) 2006-2007, Digium, Inc.
+ * Copyright (C) 2006-2008, Digium, Inc.
*
* All rights reserved.
*
@@ -35,20 +35,11 @@
#include <linux/mm.h>
#include <linux/page-flags.h>
#include <asm/io.h>
-#ifdef CONFIG_DEVFS_FS
-#include <linux/devfs_fs_kernel.h>
-#endif
-#ifdef STANDALONE_ZAPATA
-#include "zaptel.h"
-#else
-#include <linux/zaptel.h>
-#endif
-#ifdef LINUX26
-#include <linux/moduleparam.h>
-#endif
-static int debug = 0;
-static struct zt_transcoder *trans;
+#include <zaptel.h>
+
+static int debug;
+LIST_HEAD(trans);
static spinlock_t translock = SPIN_LOCK_UNLOCKED;
EXPORT_SYMBOL(zt_transcoder_register);
@@ -59,387 +50,375 @@ EXPORT_SYMBOL(zt_transcoder_free);
struct zt_transcoder *zt_transcoder_alloc(int numchans)
{
- struct zt_transcoder *ztc;
+ struct zt_transcoder *tc;
unsigned int x;
- size_t size = sizeof(*ztc) + (sizeof(ztc->channels[0]) * numchans);
+ size_t size = sizeof(*tc) + (sizeof(tc->channels[0]) * numchans);
- if (!(ztc = kmalloc(size, GFP_KERNEL)))
+ if (!(tc = kmalloc(size, GFP_KERNEL)))
return NULL;
- memset(ztc, 0, size);
- strcpy(ztc->name, "<unspecified>");
- ztc->numchannels = numchans;
- for (x=0;x<ztc->numchannels;x++) {
- init_waitqueue_head(&ztc->channels[x].ready);
- ztc->channels[x].parent = ztc;
- ztc->channels[x].offset = x;
- ztc->channels[x].chan_built = 0;
- ztc->channels[x].built_fmts = 0;
+ memset(tc, 0, size);
+ strcpy(tc->name, "<unspecified>");
+ tc->numchannels = numchans;
+ for (x=0;x<tc->numchannels;x++) {
+ init_waitqueue_head(&tc->channels[x].ready);
+ INIT_LIST_HEAD(&tc->node);
+ tc->channels[x].parent = tc;
}
- return ztc;
+ WARN_ON(!zt_transcode_fops);
+ /* Individual transcoders should supply their own file_operations for
+ * write and read. But they will by default use the file_operations
+ * provided by the zt_transcode layer. */
+ memcpy(&tc->fops, zt_transcode_fops, sizeof(*zt_transcode_fops));
+ return tc;
}
-static int schluffen(wait_queue_head_t *q)
+void zt_transcoder_free(struct zt_transcoder *tc)
{
- DECLARE_WAITQUEUE(wait, current);
-
- add_wait_queue(q, &wait);
- current->state = TASK_INTERRUPTIBLE;
-
- if (!signal_pending(current))
- schedule();
-
- current->state = TASK_RUNNING;
- remove_wait_queue(q, &wait);
-
- if (signal_pending(current))
- return -ERESTARTSYS;
-
- return 0;
+ kfree(tc);
}
-void zt_transcoder_free(struct zt_transcoder *ztc)
+/* Returns 1 if the item is on the list pointed to by head, otherwise, returns
+ * 0 */
+static int is_on_list(struct list_head *entry, struct list_head *head)
{
- kfree(ztc);
+ struct list_head *cur;
+ list_for_each(cur, head) {
+ if (cur == entry) return 1;
+ }
+ return 0;
}
/* Register a transcoder */
int zt_transcoder_register(struct zt_transcoder *tc)
{
- struct zt_transcoder *cur;
- int res = -EBUSY;
-
spin_lock(&translock);
- for (cur = trans; cur; cur = cur->next) {
- if (cur == tc) {
- spin_unlock(&translock);
- return res;
- }
- }
-
- tc->next = trans;
- trans = tc;
- printk("Registered codec translator '%s' with %d transcoders (srcs=%08x, dsts=%08x)\n",
- tc->name, tc->numchannels, tc->srcfmts, tc->dstfmts);
- res = 0;
+ BUG_ON(is_on_list(&tc->node, &trans));
+ list_add_tail(&tc->node, &trans);
spin_unlock(&translock);
- return res;
+ printk(KERN_INFO "%s: Registered codec translator '%s' " \
+ "with %d transcoders (srcs=%08x, dsts=%08x)\n",
+ THIS_MODULE->name, tc->name, tc->numchannels,
+ tc->srcfmts, tc->dstfmts);
+
+ return 0;
}
/* Unregister a transcoder */
int zt_transcoder_unregister(struct zt_transcoder *tc)
{
- struct zt_transcoder *cur, *prev;
int res = -EINVAL;
- spin_lock(&translock);
- for (cur = trans, prev = NULL; cur; prev = cur, cur = cur->next) {
- if (cur == tc)
- break;
- }
+ /* \todo Perhaps we should check to make sure there isn't a channel
+ * that is still in use? */
- if (!cur) {
+ spin_lock(&translock);
+ if (!is_on_list(&tc->node, &trans)) {
spin_unlock(&translock);
- return res;
+ printk(KERN_WARNING "%s: Failed to unregister %s, which is " \
+ "not currently registerd.\n", THIS_MODULE->name, tc->name);
+ return -EINVAL;
}
+ list_del_init(&tc->node);
+ spin_unlock(&translock);
- if (prev)
- prev->next = tc->next;
- else
- trans = tc->next;
- tc->next = NULL;
- printk("Unregistered codec translator '%s' with %d transcoders (srcs=%08x, dsts=%08x)\n",
+ printk(KERN_INFO "Unregistered codec translator '%s' with %d " \
+ "transcoders (srcs=%08x, dsts=%08x)\n",
tc->name, tc->numchannels, tc->srcfmts, tc->dstfmts);
res = 0;
- spin_unlock(&translock);
return res;
}
/* Alert a transcoder */
-int zt_transcoder_alert(struct zt_transcoder_channel *ztc)
+int zt_transcoder_alert(struct zt_transcoder_channel *chan)
{
- if (debug)
- printk("ZT Transcoder Alert!\n");
- if (ztc->tch)
- ztc->tch->status &= ~ZT_TC_FLAG_BUSY;
- wake_up_interruptible(&ztc->ready);
-
+ wake_up_interruptible(&chan->ready);
return 0;
}
static int zt_tc_open(struct inode *inode, struct file *file)
{
- struct zt_transcoder_channel *ztc;
- struct zt_transcode_header *zth;
- struct page *page;
-
- if (!(ztc = kmalloc(sizeof(*ztc), GFP_KERNEL)))
- return -ENOMEM;
-
- if (!(zth = kmalloc(sizeof(*zth), GFP_KERNEL | GFP_DMA))) {
- kfree(ztc);
- return -ENOMEM;
- }
-
- memset(ztc, 0, sizeof(*ztc));
- memset(zth, 0, sizeof(*zth));
- ztc->flags = ZT_TC_FLAG_TRANSIENT | ZT_TC_FLAG_BUSY;
- ztc->tch = zth;
- if (debug)
- printk("Allocated Transcoder Channel, header is at %p!\n", zth);
- zth->magic = ZT_TRANSCODE_MAGIC;
- file->private_data = ztc;
- for (page = virt_to_page(zth);
- page < virt_to_page((unsigned long) zth + sizeof(*zth));
- page++)
- SetPageReserved(page);
-
+ const struct file_operations *original_fops;
+ BUG_ON(!zt_transcode_fops);
+ original_fops = file->f_op;
+ file->f_op = zt_transcode_fops;
+ file->private_data = NULL;
+ /* Under normal operation, this releases the reference on the Zaptel
+ * module that was created when the file was opened. zt_open is
+ * responsible for taking a reference out on this module before
+ * calling this function. */
+ module_put(original_fops->owner);
return 0;
}
-static void ztc_release(struct zt_transcoder_channel *ztc)
+static void dtc_release(struct zt_transcoder_channel *chan)
{
- struct zt_transcode_header *zth = ztc->tch;
- struct page *page;
-
- if (!ztc)
- return;
-
- ztc->flags &= ~(ZT_TC_FLAG_BUSY);
-
- if(ztc->tch) {
- for (page = virt_to_page(zth);
- page < virt_to_page((unsigned long) zth + sizeof(*zth));
- page++)
- ClearPageReserved(page);
- kfree(ztc->tch);
+ BUG_ON(!chan);
+ if (chan->parent && chan->parent->release) {
+ chan->parent->release(chan);
}
-
- ztc->tch = NULL;
- /* Actually reset the transcoder channel */
- if (ztc->flags & ZT_TC_FLAG_TRANSIENT)
- kfree(ztc);
- if (debug)
- printk("Released Transcoder!\n");
+ zt_tc_clear_busy(chan);
}
static int zt_tc_release(struct inode *inode, struct file *file)
{
- ztc_release(file->private_data);
-
+ struct zt_transcoder_channel *chan = file->private_data;
+ /* There will not be a transcoder channel associated with this file if
+ * the ALLOCATE ioctl never succeeded.
+ */
+ if (chan) {
+ dtc_release(chan);
+ }
return 0;
}
-static int do_reset(struct zt_transcoder_channel **ztc)
+/* Find a free channel on the transcoder and mark it busy. */
+static inline struct zt_transcoder_channel *
+get_free_channel(struct zt_transcoder *tc)
+
+{
+ struct zt_transcoder_channel *chan;
+ int i;
+ /* Should be called with the translock held. */
+ WARN_ON(!spin_is_locked(&translock));
+
+ for (i = 0; i < tc->numchannels; i++) {
+ chan = &tc->channels[i];
+ if (!zt_tc_is_busy(chan)) {
+ zt_tc_set_busy(chan);
+ return chan;
+ }
+ }
+ return NULL;
+}
+
+/* Search the list for a transcoder that supports the specified format, and
+ * allocate and return an available channel on it.
+ *
+ * Returns either a pointer to the allocated channel, -EBUSY if the format is
+ * supported but all the channels are busy, or -ENODEV if there are not any
+ * transcoders that support the formats.
+ */
+static struct zt_transcoder_channel *
+__find_free_channel(struct list_head *list, const struct zt_transcoder_formats *fmts)
{
- struct zt_transcoder_channel *newztc = NULL, *origztc = NULL;
- struct zt_transcode_header *zth = (*ztc)->tch;
struct zt_transcoder *tc;
- unsigned int x;
+ struct zt_transcoder_channel *chan = NULL;
unsigned int match = 0;
- if (((*ztc)->srcfmt != zth->srcfmt) ||
- ((*ztc)->dstfmt != zth->dstfmt)) {
- /* Find new transcoder */
- spin_lock(&translock);
- for (tc = trans; tc && !newztc; tc = tc->next) {
- if (!(tc->srcfmts & zth->srcfmt))
- continue;
-
- if (!(tc->dstfmts & zth->dstfmt))
- continue;
-
- match = 1;
- for (x = 0; x < tc->numchannels; x++) {
- if (tc->channels[x].flags & ZT_TC_FLAG_BUSY)
- continue;
- if ((tc->channels[x].chan_built) && ((zth->srcfmt | zth->dstfmt) != tc->channels[x].built_fmts))
- continue;
-
- newztc = &tc->channels[x];
- newztc->flags = ZT_TC_FLAG_BUSY;
- break;
+ list_for_each_entry(tc, list, node) {
+ if ((tc->dstfmts & fmts->dstfmt)) {
+ /* We found a transcoder that can handle our formats.
+ * Now look for an available channel. */
+ match = 1;
+ if ((chan = get_free_channel(tc))) {
+ /* transcoder tc has a free channel. In order
+ * to spread the load among available
+ * transcoders (when there are more than one
+ * transcoder in the system) we'll move tc
+ * to the end of the list. */
+ list_move_tail(&tc->node, list);
+ return chan;
}
}
- spin_unlock(&translock);
+ }
+ return (void*)((long)((match) ? -EBUSY : -ENODEV));
+}
- if (!newztc)
- return match ? -EBUSY : -ENOSYS;
+static long zt_tc_allocate(struct file *file, unsigned long data)
+{
+ struct zt_transcoder_channel *chan = NULL;
+ struct zt_transcoder_formats fmts;
+
+ if (copy_from_user(&fmts,
+ (struct zt_transcoder_formats*) data, sizeof(fmts))) {
+ return -EFAULT;
+ }
+
+ spin_lock(&translock);
+ chan = __find_free_channel(&trans, &fmts);
+ spin_unlock(&translock);
- /* Move transcoder header over */
- origztc = (*ztc);
- (*ztc) = newztc;
- (*ztc)->tch = origztc->tch;
- origztc->tch = NULL;
- (*ztc)->flags |= (origztc->flags & ~(ZT_TC_FLAG_TRANSIENT));
- ztc_release(origztc);
+ if (IS_ERR(chan)) {
+ return PTR_ERR(chan);
}
- /* Actually reset the transcoder channel */
- if ((*ztc)->parent && ((*ztc)->parent->operation))
- return (*ztc)->parent->operation((*ztc), ZT_TCOP_ALLOCATE);
+ /* Every transcoder channel must be associated with a parent
+ * transcoder. */
+ BUG_ON(!chan->parent);
- return -EINVAL;
-}
+ chan->srcfmt = fmts.srcfmt;
+ chan->dstfmt = fmts.dstfmt;
-static int wait_busy(struct zt_transcoder_channel *ztc)
-{
- int ret;
+ if (file->private_data) {
+ /* This open file is moving to a new channel. Cleanup and
+ * close the old channel here. */
+ dtc_release(file->private_data);
+ }
+
+ file->private_data = chan;
+ if (chan->parent->fops.owner != file->f_op->owner) {
+ if (!try_module_get(chan->parent->fops.owner)) {
+ /* Failed to get a reference on the driver for the
+ * actual transcoding hardware. */
+ return -EINVAL;
+ }
+ /* Release the reference on the existing driver. */
+ module_put(file->f_op->owner);
+ file->f_op = &chan->parent->fops;
+ }
- for (;;) {
- if (!(ztc->tch->status & ZT_TC_FLAG_BUSY))
- return 0;
- if ((ret = schluffen(&ztc->ready)))
- return ret;
+ if (file->f_flags & O_NONBLOCK) {
+ zt_tc_set_nonblock(chan);
+ } else {
+ zt_tc_clear_nonblock(chan);
}
+
+ /* Actually reset the transcoder channel */
+ if (chan->parent->allocate)
+ return chan->parent->allocate(chan);
+
+ return -EINVAL;
}
-static int zt_tc_getinfo(unsigned long data)
+static long zt_tc_getinfo(unsigned long data)
{
- struct zt_transcode_info info;
+ struct zt_transcoder_info info;
unsigned int x;
- struct zt_transcoder *tc;
+ struct zt_transcoder *cur;
+ struct zt_transcoder *tc = NULL;
- if (copy_from_user(&info, (struct zt_transcode_info *) data, sizeof(info)))
+ if (copy_from_user(&info, (const void *) data, sizeof(info))) {
return -EFAULT;
+ }
+ x = 0;
spin_lock(&translock);
- for (tc = trans, x = info.tcnum; tc && x; tc = tc->next, x--);
+ list_for_each_entry(cur, &trans, node) {
+ if (x++ == info.tcnum) {
+ tc = cur;
+ break;
+ }
+ }
spin_unlock(&translock);
- if (!tc)
+ if (!tc) {
return -ENOSYS;
+ }
zap_copy_string(info.name, tc->name, sizeof(info.name));
info.numchannels = tc->numchannels;
info.srcfmts = tc->srcfmts;
info.dstfmts = tc->dstfmts;
- return copy_to_user((struct zt_transcode_info *) data, &info, sizeof(info)) ? -EFAULT : 0;
+ return copy_to_user((void *) data, &info, sizeof(info)) ? -EFAULT : 0;
}
-static int zt_tc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data)
+static ssize_t zt_tc_write(struct file *file, __user const char *usrbuf, size_t count, loff_t *ppos)
{
- int op;
- int ret;
- struct zt_transcoder_channel *ztc = file->private_data;
-
- if (cmd != ZT_TRANSCODE_OP)
+ if (file->private_data) {
+ /* file->private_data will not be NULL if ZT_TC_ALLOCATE was
+ * called, and therefore indicates that the transcoder driver
+ * did not export a read function. */
+ WARN_ON(1);
return -ENOSYS;
-
- if (get_user(op, (int *) data))
- return -EFAULT;
-
- if (debug)
- printk("ZT Transcode ioctl op = %d!\n", op);
-
- switch(op) {
- case ZT_TCOP_GETINFO:
- ret = zt_tc_getinfo(data);
- break;
- case ZT_TCOP_ALLOCATE:
- /* Reset transcoder, possibly changing who we point to */
- ret = do_reset(&ztc);
- file->private_data = ztc;
- break;
- case ZT_TCOP_RELEASE:
- ret = ztc->parent->operation(ztc, ZT_TCOP_RELEASE);
- break;
- case ZT_TCOP_TEST:
- ret = ztc->parent->operation(ztc, ZT_TCOP_TEST);
- break;
- case ZT_TCOP_TRANSCODE:
- if (!ztc->parent->operation)
- return -EINVAL;
-
- ztc->tch->status |= ZT_TC_FLAG_BUSY;
- if (!(ret = ztc->parent->operation(ztc, ZT_TCOP_TRANSCODE))) {
- /* Wait for busy to go away if we're not non-blocking */
- if (!(file->f_flags & O_NONBLOCK)) {
- if (!(ret = wait_busy(ztc)))
- ret = ztc->errorstatus;
- }
- } else
- ztc->tch->status &= ~ZT_TC_FLAG_BUSY;
- break;
- default:
- ret = -ENOSYS;
+ } else {
+ printk(KERN_INFO "%s: Attempt to write to unallocated " \
+ "channel.\n", THIS_MODULE->name);
+ return -EINVAL;
}
-
- return ret;
}
-static int zt_tc_mmap(struct file *file, struct vm_area_struct *vma)
+static ssize_t zt_tc_read(struct file *file, __user char *usrbuf, size_t count, loff_t *ppos)
{
- struct zt_transcoder_channel *ztc = file->private_data;
- unsigned long physical;
- int res;
-
- if (!ztc)
- return -EINVAL;
-
- /* Do not allow an offset */
- if (vma->vm_pgoff) {
- if (debug)
- printk("zttranscode: Attempted to mmap with offset!\n");
+ if (file->private_data) {
+ /* file->private_data will not be NULL if ZT_TC_ALLOCATE was
+ * called, and therefore indicates that the transcoder driver
+ * did not export a write function. */
+ WARN_ON(1);
+ return -ENOSYS;
+ } else {
+ printk(KERN_INFO "%s: Attempt to read from unallocated " \
+ "channel.\n", THIS_MODULE->name);
return -EINVAL;
}
+}
- if ((vma->vm_end - vma->vm_start) != sizeof(struct zt_transcode_header)) {
- if (debug)
- printk("zttranscode: Attempted to mmap with size %d != %zd!\n", (int) (vma->vm_end - vma->vm_start), sizeof(struct zt_transcode_header));
+static long zt_tc_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long data)
+{
+ switch (cmd) {
+ case ZT_TC_ALLOCATE:
+ return zt_tc_allocate(file, data);
+ case ZT_TC_GETINFO:
+ return zt_tc_getinfo(data);
+ case ZT_TRANSCODE_OP:
+ /* This is a deprecated call from the previous transcoder
+ * interface, which was all routed through the zt_ioctl in
+ * zaptel-base.c, and this ioctl request was used to indicate
+ * that the call should be forwarded to this function. Now
+ * when the file is opened, the f_ops pointer is updated to
+ * point directly to this function, and we don't need a
+ * general indication that the ioctl is destined for the
+ * transcoder.
+ *
+ * I'm keeping this ioctl here in order to explain why there
+ * might be a hole in the ioctl numbering scheme in the header
+ * files.
+ */
+ printk(KERN_WARNING "%s: ZT_TRANSCODE_OP is no longer " \
+ "supported. Please call ZT_TC ioctls directly.\n",
+ THIS_MODULE->name);
return -EINVAL;
- }
-
- physical = (unsigned long) virt_to_phys(ztc->tch);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
- res = remap_pfn_range(vma, vma->vm_start, physical >> PAGE_SHIFT, sizeof(struct zt_transcode_header), PAGE_SHARED);
-#else
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
- res = remap_page_range(vma->vm_start, physical, sizeof(struct zt_transcode_header), PAGE_SHARED);
- #else
- res = remap_page_range(vma, vma->vm_start, physical, sizeof(struct zt_transcode_header), PAGE_SHARED);
- #endif
-#endif
- if (res) {
- if (debug)
- printk("zttranscode: remap failed!\n");
- return -EAGAIN;
- }
+ default:
+ return -EINVAL;
+ };
+}
- if (debug)
- printk("zttranscode: successfully mapped transcoder!\n");
+static int zt_tc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data)
+{
+ return (int)zt_tc_unlocked_ioctl(file, cmd, data);
+}
- return 0;
+static int zt_tc_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ printk(KERN_ERR "%s: mmap interface deprecated.\n", THIS_MODULE->name);
+ return -ENOSYS;
}
static unsigned int zt_tc_poll(struct file *file, struct poll_table_struct *wait_table)
{
- struct zt_transcoder_channel *ztc = file->private_data;
+ int ret;
+ struct zt_transcoder_channel *chan = file->private_data;
- if (!ztc)
+ if (!chan) {
+ /* This is because the ZT_TC_ALLOCATE ioctl was not called
+ * before calling poll, which is invalid. */
return -EINVAL;
+ }
- poll_wait(file, &ztc->ready, wait_table);
- return ztc->tch->status & ZT_TC_FLAG_BUSY ? 0 : POLLPRI;
+ poll_wait(file, &chan->ready, wait_table);
+
+ ret = zt_tc_is_busy(chan) ? 0 : POLLPRI;
+ ret |= zt_tc_is_built(chan) ? POLLOUT : 0;
+ ret |= zt_tc_is_data_waiting(chan) ? POLLIN : 0;
+ return ret;
}
static struct file_operations __zt_transcode_fops = {
- owner: THIS_MODULE,
- llseek: NULL,
- open: zt_tc_open,
+ owner: THIS_MODULE,
+ open: zt_tc_open,
release: zt_tc_release,
- ioctl: zt_tc_ioctl,
- read: NULL,
- write: NULL,
- poll: zt_tc_poll,
- mmap: zt_tc_mmap,
- flush: NULL,
- fsync: NULL,
- fasync: NULL,
+ ioctl: zt_tc_ioctl,
+ read: zt_tc_read,
+ write: zt_tc_write,
+ poll: zt_tc_poll,
+ mmap: zt_tc_mmap,
+#if HAVE_UNLOCKED_IOCTL
+ unlocked_ioctl: zt_tc_unlocked_ioctl,
+#endif
};
static struct zt_chardev transcode_chardev = {
@@ -447,12 +426,12 @@ static struct zt_chardev transcode_chardev = {
.minor = 250,
};
-int zttranscode_init(void)
+int zt_transcode_init(void)
{
int res;
if (zt_transcode_fops) {
- printk("Whoa, zt_transcode_fops already set?!\n");
+ printk(KERN_WARNING "zt_transcode_fops already set.\n");
return -EBUSY;
}
@@ -461,30 +440,25 @@ int zttranscode_init(void)
if ((res = zt_register_chardev(&transcode_chardev)))
return res;
- printk("Zaptel Transcoder support loaded\n");
-
+ printk(KERN_INFO "%s: Loaded.\n", THIS_MODULE->name);
return 0;
}
-void zttranscode_cleanup(void)
+void zt_transcode_cleanup(void)
{
zt_unregister_chardev(&transcode_chardev);
zt_transcode_fops = NULL;
- printk("Zaptel Transcoder support unloaded\n");
+ printk(KERN_DEBUG "%s: Unloaded.\n", THIS_MODULE->name);
}
-#ifdef LINUX26
module_param(debug, int, S_IRUGO | S_IWUSR);
-#else
-MODULE_PARM(debug, "i");
-#endif
MODULE_DESCRIPTION("Zaptel Transcoder Support");
MODULE_AUTHOR("Mark Spencer <markster@digium.com>");
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif
-module_init(zttranscode_init);
-module_exit(zttranscode_cleanup);
+module_init(zt_transcode_init);
+module_exit(zt_transcode_cleanup);