Skip to content
Snippets Groups Projects
Commit a0547eea authored by Florian Pose's avatar Florian Pose
Browse files

Interface management.

parent 3f89ea93
No related branches found
No related tags found
No related merge requests found
/******************************************************************************
*
* $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
...@@ -38,17 +38,23 @@ ...@@ -38,17 +38,23 @@
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/tty_driver.h> #include <linux/tty_driver.h>
#include <linux/termios.h> #include <linux/termios.h>
#include <linux/semaphore.h>
#include "../master/globals.h" #include "../master/globals.h"
#include "../include/ectty.h"
/*****************************************************************************/ /*****************************************************************************/
int __init ec_tty_init_module(void); #define EC_TTY_MAX_DEVICES 10
void __exit ec_tty_cleanup_module(void);
/*****************************************************************************/
unsigned int debug_level = 0;
char *ec_master_version_str = EC_MASTER_VERSION; /**< Version string. */ 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 */ /** \cond */
...@@ -58,11 +64,11 @@ MODULE_DESCRIPTION("EtherCAT TTY driver module"); ...@@ -58,11 +64,11 @@ MODULE_DESCRIPTION("EtherCAT TTY driver module");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_VERSION(EC_MASTER_VERSION); MODULE_VERSION(EC_MASTER_VERSION);
unsigned int debug_level = 0;
module_param_named(debug_level, debug_level, uint, S_IRUGO); module_param_named(debug_level, debug_level, uint, S_IRUGO);
MODULE_PARM_DESC(debug_level, "Debug level"); MODULE_PARM_DESC(debug_level, "Debug level");
struct tty_driver *tty_driver = NULL; /** \endcond */
struct device *tty_device = NULL;
static int ec_tty_open(struct tty_struct *, struct file *); static int ec_tty_open(struct tty_struct *, struct file *);
static void ec_tty_close(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 = { ...@@ -82,7 +88,10 @@ static struct ktermios ec_tty_std_termios = {
.c_cc = INIT_C_CC, .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 = { ...@@ -92,11 +101,17 @@ static struct ktermios ec_tty_std_termios = {
*/ */
int __init ec_tty_init_module(void) int __init ec_tty_init_module(void)
{ {
int ret = 0; int i, ret = 0;
EC_INFO("TTY driver %s\n", EC_MASTER_VERSION); 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) { if (!tty_driver) {
EC_ERR("Failed to allocate tty driver.\n"); EC_ERR("Failed to allocate tty driver.\n");
ret = -ENOMEM; ret = -ENOMEM;
...@@ -121,17 +136,8 @@ int __init ec_tty_init_module(void) ...@@ -121,17 +136,8 @@ int __init ec_tty_init_module(void)
goto out_put; 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; return ret;
out_unreg:
tty_unregister_driver(tty_driver);
out_put: out_put:
put_tty_driver(tty_driver); put_tty_driver(tty_driver);
out_return: out_return:
...@@ -146,7 +152,6 @@ out_return: ...@@ -146,7 +152,6 @@ out_return:
*/ */
void __exit ec_tty_cleanup_module(void) void __exit ec_tty_cleanup_module(void)
{ {
tty_unregister_device(tty_driver, 0);
tty_unregister_driver(tty_driver); tty_unregister_driver(tty_driver);
put_tty_driver(tty_driver); put_tty_driver(tty_driver);
EC_INFO("TTY module cleaned up.\n"); EC_INFO("TTY module cleaned up.\n");
...@@ -154,6 +159,30 @@ void __exit ec_tty_cleanup_module(void) ...@@ -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) static int ec_tty_open(struct tty_struct *tty, struct file *file)
{ {
return -EBUSY; return -EBUSY;
...@@ -177,6 +206,55 @@ static int ec_tty_write( ...@@ -177,6 +206,55 @@ static int ec_tty_write(
return -EIO; 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 */ /** \cond */
...@@ -184,6 +262,9 @@ static int ec_tty_write( ...@@ -184,6 +262,9 @@ static int ec_tty_write(
module_init(ec_tty_init_module); module_init(ec_tty_init_module);
module_exit(ec_tty_cleanup_module); module_exit(ec_tty_cleanup_module);
EXPORT_SYMBOL(ectty_create);
EXPORT_SYMBOL(ectty_free);
/** \endcond */ /** \endcond */
/*****************************************************************************/ /*****************************************************************************/
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment