diff options
author | blogic <blogic@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2010-11-03 19:12:34 +0000 |
---|---|---|
committer | blogic <blogic@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2010-11-03 19:12:34 +0000 |
commit | 6ea7ec75d2fe0dd52bc3e86135412bfc92c3158c (patch) | |
tree | 1b900bd32ce90c62703905c460db950c7c2ba9ec /package/lqtapi/src/tapi/tapi-core.c | |
parent | 74f6f2f5a244b9ba7aec5d7114fe763f8c20e96c (diff) |
[ifxmips]
* adds a rewrite of the tapi drivers + sip app. this is the result of lars' gsoc 2010 project, Thanks !
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@23840 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'package/lqtapi/src/tapi/tapi-core.c')
-rw-r--r-- | package/lqtapi/src/tapi/tapi-core.c | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/package/lqtapi/src/tapi/tapi-core.c b/package/lqtapi/src/tapi/tapi-core.c new file mode 100644 index 000000000..2e112a376 --- /dev/null +++ b/package/lqtapi/src/tapi/tapi-core.c @@ -0,0 +1,250 @@ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/device.h> +#include <linux/list.h> + +#include <linux/cdev.h> +#include <linux/err.h> + +#include <linux/tapi/tapi.h> + + +void tapi_alloc_input(struct tapi_device *tdev, struct tapi_port *port); +int tapi_register_port_device(struct tapi_device* tdev, struct tapi_port *port); +int tapi_register_stream_device(struct tapi_device* tdev); +int tapi_register_control_device(struct tapi_device* tdev); + +static struct class *tapi_class; +static int tapi_major; + +#define TAPI_MAX_MINORS 255 + +static bool tapi_minors[TAPI_MAX_MINORS]; + +static int tapi_get_free_minor(void) +{ + int i; + for (i = 0; i < TAPI_MAX_MINORS; ++i) { + if (!tapi_minors[i]) { + tapi_minors[i] = true; + return i; + } + } + + return -1; +} + +/* +int tapi_port_send_dtmf_events(struct tapi_device *tdev, unsigned int port, struct tapi_dtmf *, size_t num_events, unsigned int dealy) +{ +} +EXPORT_SYMBOL_GPL(tapi_port_send_dtmf_events); +*/ + +void tapi_report_hook_event(struct tapi_device *tdev, struct tapi_port *port, + bool on) +{ + struct tapi_event event; + event.type = TAPI_EVENT_TYPE_HOOK; + event.port = port->id; + event.hook.on = on; + + tapi_report_event(tdev, &event); +} +EXPORT_SYMBOL_GPL(tapi_report_hook_event); + +void tapi_report_dtmf_event(struct tapi_device *tdev, struct tapi_port *port, + unsigned char code) +{ + struct tapi_event event; + event.type = TAPI_EVENT_TYPE_DTMF; + event.port = port->id; + event.dtmf.code = code; + + tapi_report_event(tdev, &event); +} +EXPORT_SYMBOL_GPL(tapi_report_dtmf_event); + +struct tapi_stream *tapi_stream_alloc(struct tapi_device *tdev) +{ + struct tapi_stream *stream; + printk("tdev %p\n", tdev); + + if (!tdev->ops || !tdev->ops->stream_alloc) + return ERR_PTR(-ENOSYS); + + stream = tdev->ops->stream_alloc(tdev); + printk("stream %p\n", stream); + if (IS_ERR(stream)) + return stream; + + stream->id = atomic_inc_return(&tdev->stream_id) - 1; + stream->ep.id = stream->id; + +/* mutex_lock(&tdev->lock);*/ + list_add_tail(&stream->head, &tdev->streams); +/* mutex_unlock(&tdev->lock);*/ + + return stream; +} +EXPORT_SYMBOL_GPL(tapi_stream_alloc); + +void tapi_stream_free(struct tapi_device *tdev, struct tapi_stream *stream) +{ + mutex_lock(&tdev->lock); + list_del(&stream->head); + mutex_unlock(&tdev->lock); + + tdev->ops->stream_free(tdev, stream); +} +EXPORT_SYMBOL_GPL(tapi_stream_free); + +struct tapi_link *tapi_link_alloc(struct tapi_device *tdev, + struct tapi_endpoint *ep1, struct tapi_endpoint *ep2) +{ + struct tapi_link *link; + + if (!tdev->ops || !tdev->ops->link_alloc) + return ERR_PTR(-ENOSYS); + + link = tdev->ops->link_alloc(tdev, ep1, ep2); + if (IS_ERR(link)) + return link; + + link->id = atomic_inc_return(&tdev->link_id) - 1; + +/* + mutex_lock(&tdev->lock); + list_add_tail(&link->head, &tdev->links); + mutex_unlock(&tdev->lock); +*/ + return link; +} +EXPORT_SYMBOL_GPL(tapi_link_alloc); + +void tapi_link_free(struct tapi_device *tdev, struct tapi_link *link) +{ +/* + mutex_lock(&tdev->lock); + list_del(&link->head); + mutex_unlock(&tdev->lock); +*/ + tdev->ops->link_free(tdev, link); +} +EXPORT_SYMBOL_GPL(tapi_link_free); + +int tapi_char_device_register(struct tapi_device *tdev, + struct tapi_char_device *tchrdev, const struct file_operations *fops) +{ + int ret; + struct device *dev = &tchrdev->dev; + dev_t devt; + int minor = tapi_get_free_minor(); + + devt = MKDEV(tapi_major, minor); + + dev->devt = devt; + dev->class = tapi_class; + dev->parent = &tdev->dev; + + tchrdev->tdev = tdev; + + cdev_init(&tchrdev->cdev, fops); + tchrdev->cdev.owner = THIS_MODULE; + ret = cdev_add(&tchrdev->cdev, devt, 1); + if (ret) + return ret; + + ret = device_register(&tchrdev->dev); + if (ret) + goto err_cdev_del; + + return 0; + +err_cdev_del: + cdev_del(&tchrdev->cdev); + + return ret; +} + +int tapi_device_register(struct tapi_device *tdev, const char *name, + struct device *parent) +{ + static atomic_t tapi_device_id = ATOMIC_INIT(0); + int ret, i; + + tdev->dev.class = tapi_class; + tdev->dev.parent = parent; + dev_set_name(&tdev->dev, "%s", name); + + ret = device_register(&tdev->dev); + if (ret) + return ret; + + tdev->id = atomic_inc_return(&tapi_device_id) - 1; + + mutex_init(&tdev->lock); + INIT_LIST_HEAD(&tdev->streams); + INIT_LIST_HEAD(&tdev->links); + atomic_set(&tdev->link_id, 0); + atomic_set(&tdev->stream_id, tdev->num_ports); + + tapi_register_stream_device(tdev); + tapi_register_control_device(tdev); + + for (i = 0; i < tdev->num_ports; ++i) { + tapi_port_alloc(tdev, i); + tapi_alloc_input(tdev, &tdev->ports[i]); + tapi_register_port_device(tdev, &tdev->ports[i]); + tdev->ports[i].id = i; + tdev->ports[i].ep.id = i; + } + + return 0; +} +EXPORT_SYMBOL_GPL(tapi_device_register); + +void tapi_device_unregister(struct tapi_device *tdev) +{ + device_unregister(&tdev->dev); +} +EXPORT_SYMBOL_GPL(tapi_device_unregister); + +static int __init tapi_class_init(void) +{ + int ret; + dev_t dev; + + tapi_class = class_create(THIS_MODULE, "tapi"); + + if (IS_ERR(tapi_class)) { + ret = PTR_ERR(tapi_class); + printk(KERN_ERR "tapi: Failed to create device class: %d\n", ret); + goto err; + } + + ret = alloc_chrdev_region(&dev, 0, TAPI_MAX_MINORS, "tapi"); + if (ret) { + printk(KERN_ERR "tapi: Failed to allocate chrdev region: %d\n", ret); + goto err_class_destory; + } + tapi_major = MAJOR(dev); + + return 0; +err_class_destory: + class_destroy(tapi_class); +err: + return ret; +} +subsys_initcall(tapi_class_init); + +static void __exit tapi_class_exit(void) +{ + unregister_chrdev_region(MKDEV(tapi_major, 0), TAPI_MAX_MINORS); + class_destroy(tapi_class); +} +module_exit(tapi_class_exit); + +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); +MODULE_DESCRIPTION("TAPI class"); +MODULE_LICENSE("GPL"); |