Interface management.

This commit is contained in:
Florian Pose 2009-12-01 21:45:45 +01:00
parent fdad28ad05
commit 866c82a4a8
2 changed files with 175 additions and 18 deletions

76
include/ectty.h Normal file
View File

@ -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
* <http://www.gnu.org/licenses/>.
*
* ---
*
* 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

View File

@ -38,17 +38,23 @@
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/termios.h>
#include <linux/semaphore.h>
#include "../master/globals.h"
#include "../include/ectty.h"
/*****************************************************************************/
int __init ec_tty_init_module(void);
void __exit ec_tty_cleanup_module(void);
#define EC_TTY_MAX_DEVICES 10
/*****************************************************************************/
unsigned int debug_level = 0;
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_DESCRIPTION("EtherCAT TTY driver module");
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 @@ static struct ktermios ec_tty_std_termios = {
.c_cc = INIT_C_CC,
};
/** \endcond */
struct ec_tty {
int minor;
struct device *dev;
};
/*****************************************************************************/
@ -92,11 +101,17 @@ static struct ktermios ec_tty_std_termios = {
*/
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 @@ int __init ec_tty_init_module(void)
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 @@ out_return:
*/
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 @@ void __exit ec_tty_cleanup_module(void)
/*****************************************************************************/
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 @@ static int ec_tty_write(
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 @@ static int ec_tty_write(
module_init(ec_tty_init_module);
module_exit(ec_tty_cleanup_module);
EXPORT_SYMBOL(ectty_create);
EXPORT_SYMBOL(ectty_free);
/** \endcond */
/*****************************************************************************/