# HG changeset patch # User Florian Pose # Date 1259700345 -3600 # Node ID 61f5f4c35883abf151daed54478005e06716c265 # Parent d9bbbe1883abf02c84fbf45b589ba75304eb3fd0 Interface management. diff -r d9bbbe1883ab -r 61f5f4c35883 include/ectty.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/ectty.h Tue Dec 01 21:45:45 2009 +0100 @@ -0,0 +1,76 @@ +/****************************************************************************** + * + * $Id$ + * + * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH + * + * This file is part of the IgH EtherCAT master userspace library. + * + * The IgH EtherCAT master userspace library is free software; you can + * redistribute it and/or modify it under the terms of the GNU Lesser General + * Public License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * The IgH EtherCAT master userspace library is distributed in the hope that + * it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the IgH EtherCAT master userspace library. If not, see + * . + * + * --- + * + * The license mentioned above concerns the source code only. Using the + * EtherCAT technology and brand is only permitted in compliance with the + * industrial property and similar rights of Beckhoff Automation GmbH. + * + *****************************************************************************/ + +/** \file + * + * EtherCAT virtual TTY interface. + * + * \defgroup TTYInterface EtherCAT Virtual TTY Interface + * + * @{ + */ + +/*****************************************************************************/ + +#ifndef __ECTTY_H__ +#define __ECTTY_H__ + +/****************************************************************************** + * Data types + *****************************************************************************/ + +struct ec_tty; +typedef struct ec_tty ec_tty_t; /**< \see ec_tty */ + +/****************************************************************************** + * Global functions + *****************************************************************************/ + +/** Create a virtual TTY interface. + * + * \return Pointer to the interface object, otherwise an ERR_PTR value. + */ +ec_tty_t *ectty_create(void); + +/****************************************************************************** + * TTY interface methods + *****************************************************************************/ + +/** Releases a virtual TTY interface. + */ +void ectty_free( + ec_tty_t *tty /**< TTY interface. */ + ); + +/*****************************************************************************/ + +/** @} */ + +#endif diff -r d9bbbe1883ab -r 61f5f4c35883 tty/module.c --- a/tty/module.c Tue Dec 01 17:35:33 2009 +0100 +++ b/tty/module.c Tue Dec 01 21:45:45 2009 +0100 @@ -38,17 +38,23 @@ #include #include #include +#include #include "../master/globals.h" - -/*****************************************************************************/ - -int __init ec_tty_init_module(void); -void __exit ec_tty_cleanup_module(void); - -unsigned int debug_level = 0; +#include "../include/ectty.h" + +/*****************************************************************************/ + +#define EC_TTY_MAX_DEVICES 10 + +/*****************************************************************************/ + char *ec_master_version_str = EC_MASTER_VERSION; /**< Version string. */ +static struct tty_driver *tty_driver = NULL; +ec_tty_t *ttys[EC_TTY_MAX_DEVICES]; +struct semaphore tty_sem; + /*****************************************************************************/ /** \cond */ @@ -58,11 +64,11 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(EC_MASTER_VERSION); +unsigned int debug_level = 0; module_param_named(debug_level, debug_level, uint, S_IRUGO); MODULE_PARM_DESC(debug_level, "Debug level"); -struct tty_driver *tty_driver = NULL; -struct device *tty_device = NULL; +/** \endcond */ static int ec_tty_open(struct tty_struct *, struct file *); static void ec_tty_close(struct tty_struct *, struct file *); @@ -82,7 +88,10 @@ .c_cc = INIT_C_CC, }; -/** \endcond */ +struct ec_tty { + int minor; + struct device *dev; +}; /*****************************************************************************/ @@ -92,11 +101,17 @@ */ int __init ec_tty_init_module(void) { - int ret = 0; + int i, ret = 0; EC_INFO("TTY driver %s\n", EC_MASTER_VERSION); - tty_driver = alloc_tty_driver(1); + init_MUTEX(&tty_sem); + + for (i = 0; i < EC_TTY_MAX_DEVICES; i++) { + ttys[i] = NULL; + } + + tty_driver = alloc_tty_driver(EC_TTY_MAX_DEVICES); if (!tty_driver) { EC_ERR("Failed to allocate tty driver.\n"); ret = -ENOMEM; @@ -121,17 +136,8 @@ goto out_put; } - tty_device = tty_register_device(tty_driver, 0, NULL); - if (IS_ERR(tty_device)) { - EC_ERR("Failed to register tty device.\n"); - ret = PTR_ERR(tty_device); - goto out_unreg; - } - return ret; -out_unreg: - tty_unregister_driver(tty_driver); out_put: put_tty_driver(tty_driver); out_return: @@ -146,7 +152,6 @@ */ void __exit ec_tty_cleanup_module(void) { - tty_unregister_device(tty_driver, 0); tty_unregister_driver(tty_driver); put_tty_driver(tty_driver); EC_INFO("TTY module cleaned up.\n"); @@ -154,6 +159,30 @@ /*****************************************************************************/ +int ec_tty_init(ec_tty_t *tty, int minor) +{ + tty->minor = minor; + + tty->dev = tty_register_device(tty_driver, tty->minor, NULL); + if (IS_ERR(tty->dev)) { + EC_ERR("Failed to register tty device.\n"); + return PTR_ERR(tty->dev); + } + + return 0; +} + +/*****************************************************************************/ + +void ec_tty_clear(ec_tty_t *tty) +{ + tty_unregister_device(tty_driver, tty->minor); +} + +/****************************************************************************** + * Device callbacks + *****************************************************************************/ + static int ec_tty_open(struct tty_struct *tty, struct file *file) { return -EBUSY; @@ -177,6 +206,55 @@ return -EIO; } +/****************************************************************************** + * Public functions and methods + *****************************************************************************/ + +ec_tty_t *ectty_create(void) +{ + ec_tty_t *tty; + int minor, ret; + + if (down_interruptible(&tty_sem)) { + return ERR_PTR(-EINTR); + } + + for (minor = 0; minor < EC_TTY_MAX_DEVICES; minor++) { + if (!ttys[minor]) { + tty = kmalloc(sizeof(ec_tty_t), GFP_KERNEL); + if (!tty) { + up(&tty_sem); + EC_ERR("Failed to allocate memory for tty device.\n"); + return ERR_PTR(-ENOMEM); + } + + ret = ec_tty_init(tty, minor); + if (ret) { + up(&tty_sem); + kfree(tty); + return ERR_PTR(ret); + } + + ttys[minor] = tty; + up(&tty_sem); + return tty; + } + } + + up(&tty_sem); + return ERR_PTR(-EBUSY); +} + +/*****************************************************************************/ + +void ectty_free(ec_tty_t *tty) +{ + int minor = tty->minor; + ec_tty_clear(tty); + ttys[minor] = NULL; + kfree(tty); +} + /*****************************************************************************/ /** \cond */ @@ -184,6 +262,9 @@ module_init(ec_tty_init_module); module_exit(ec_tty_cleanup_module); +EXPORT_SYMBOL(ectty_create); +EXPORT_SYMBOL(ectty_free); + /** \endcond */ /*****************************************************************************/