mirror of
https://gitlab.com/etherlab.org/ethercat.git
synced 2026-02-06 03:41:52 +08:00
Passing tty cflag to serial implementation.
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/termios.h>
|
||||
|
||||
#include "../../include/ecrt.h" // EtherCAT realtime interface
|
||||
#include "../../include/ectty.h" // EtherCAT TTY interface
|
||||
@@ -200,12 +201,45 @@ ec_sync_info_t el6002_syncs[] = {
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
int el6002_cflag_changed(void *data, unsigned short cflag)
|
||||
{
|
||||
el6002_t *ser = (el6002_t *) data;
|
||||
int cs = 0, stop, par;
|
||||
|
||||
printk(KERN_INFO PFX "%s(data=%p, cflag=%x).\n", __func__, ser, cflag);
|
||||
|
||||
switch (cflag & CSIZE) {
|
||||
case CS7:
|
||||
cs = 7;
|
||||
break;
|
||||
case CS8:
|
||||
cs = 8;
|
||||
break;
|
||||
default: /* CS5 or CS6 */
|
||||
return -EINVAL; // not supported
|
||||
}
|
||||
|
||||
stop = (cflag & CSTOPB) ? 2 : 1;
|
||||
|
||||
if (cflag & PARENB) {
|
||||
par = (cflag & PARODD) ? 1 : 2;
|
||||
} else {
|
||||
par = 0;
|
||||
}
|
||||
|
||||
printk(KERN_INFO PFX "CS%u stopb=%u par=%i.\n", cs, stop, par);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
int el6002_init(el6002_t *ser, ec_master_t *master, u16 position,
|
||||
ec_domain_t *domain)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ser->tty = ectty_create();
|
||||
ser->tty = ectty_create(el6002_cflag_changed, ser);
|
||||
if (IS_ERR(ser->tty)) {
|
||||
printk(KERN_ERR PFX "Failed to create tty.\n");
|
||||
ret = PTR_ERR(ser->tty);
|
||||
|
||||
@@ -54,10 +54,19 @@ typedef struct ec_tty ec_tty_t; /**< \see ec_tty */
|
||||
*****************************************************************************/
|
||||
|
||||
/** Create a virtual TTY interface.
|
||||
*
|
||||
*
|
||||
* \param cflag_cb This callback function is called when the serial settings
|
||||
* shall be changed. The \a cb_data argument is the same as the \a cb_data
|
||||
* given on device creation, while the \a cflag argument contains the new
|
||||
* settings.
|
||||
* \param cb_data Arbitrary data to pass to callbacks.
|
||||
*
|
||||
* \return Pointer to the interface object, otherwise an ERR_PTR value.
|
||||
*/
|
||||
ec_tty_t *ectty_create(void);
|
||||
ec_tty_t *ectty_create(
|
||||
int (*cflag_cb)(void *cb_data, unsigned short cflag),
|
||||
void *cb_data
|
||||
);
|
||||
|
||||
/******************************************************************************
|
||||
* TTY interface methods
|
||||
|
||||
82
tty/module.c
82
tty/module.c
@@ -107,6 +107,9 @@ struct ec_tty {
|
||||
|
||||
struct timer_list timer;
|
||||
struct tty_struct *tty;
|
||||
|
||||
int (*cflag_cb)(void *, unsigned short);
|
||||
void *cb_data;
|
||||
};
|
||||
|
||||
static const struct tty_operations ec_tty_ops; // see below
|
||||
@@ -242,10 +245,10 @@ void ec_tty_wakeup(unsigned long data)
|
||||
unsigned char *cbuf;
|
||||
int space = tty_prepare_flip_string(tty->tty, &cbuf, to_recv);
|
||||
|
||||
if (space < to_recv) {
|
||||
printk(KERN_WARNING PFX "Insufficient space to_recv=%d space=%d\n",
|
||||
if (space < to_recv) {
|
||||
printk(KERN_WARNING PFX "Insufficient space to_recv=%d space=%d\n",
|
||||
to_recv, space);
|
||||
}
|
||||
}
|
||||
|
||||
if (space < 0) {
|
||||
to_recv = 0;
|
||||
@@ -266,7 +269,7 @@ void ec_tty_wakeup(unsigned long data)
|
||||
}
|
||||
tty_flip_buffer_push(tty->tty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tty->timer.expires += 1;
|
||||
add_timer(&tty->timer);
|
||||
@@ -274,7 +277,8 @@ void ec_tty_wakeup(unsigned long data)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int ec_tty_init(ec_tty_t *tty, int minor)
|
||||
int ec_tty_init(ec_tty_t *tty, int minor,
|
||||
int (*cflag_cb)(void *, unsigned short), void *cb_data)
|
||||
{
|
||||
tty->minor = minor;
|
||||
tty->tx_read_idx = 0;
|
||||
@@ -284,6 +288,8 @@ int ec_tty_init(ec_tty_t *tty, int minor)
|
||||
tty->rx_write_idx = 0;
|
||||
init_timer(&tty->timer);
|
||||
tty->tty = NULL;
|
||||
tty->cflag_cb = cflag_cb;
|
||||
tty->cb_data = cb_data;
|
||||
|
||||
tty->dev = tty_register_device(tty_driver, tty->minor, NULL);
|
||||
if (IS_ERR(tty->dev)) {
|
||||
@@ -310,17 +316,17 @@ void ec_tty_clear(ec_tty_t *tty)
|
||||
|
||||
int ec_tty_get_serial_info(ec_tty_t *tty, struct serial_struct *data)
|
||||
{
|
||||
struct serial_struct tmp;
|
||||
|
||||
if (!data)
|
||||
return -EFAULT;
|
||||
struct serial_struct tmp;
|
||||
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
|
||||
if (copy_to_user(data, &tmp, sizeof(*data))) {
|
||||
if (!data)
|
||||
return -EFAULT;
|
||||
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
|
||||
if (copy_to_user(data, &tmp, sizeof(*data))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
@@ -336,8 +342,8 @@ static int ec_tty_open(struct tty_struct *tty, struct file *file)
|
||||
printk(KERN_INFO PFX "Opening line %i.\n", line);
|
||||
#endif
|
||||
|
||||
if (line < 0 || line >= EC_TTY_MAX_DEVICES) {
|
||||
return -ENXIO;
|
||||
if (line < 0 || line >= EC_TTY_MAX_DEVICES) {
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
t = ttys[line];
|
||||
@@ -474,7 +480,7 @@ static void ec_tty_flush_buffer(struct tty_struct *tty)
|
||||
/*****************************************************************************/
|
||||
|
||||
static int ec_tty_ioctl(struct tty_struct *tty, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
ec_tty_t *t = (ec_tty_t *) tty->driver_data;
|
||||
int ret = -ENOTTY;
|
||||
@@ -487,8 +493,8 @@ static int ec_tty_ioctl(struct tty_struct *tty, struct file *file,
|
||||
#endif
|
||||
|
||||
switch (cmd) {
|
||||
case TIOCGSERIAL:
|
||||
if (access_ok(VERIFY_WRITE,
|
||||
case TIOCGSERIAL:
|
||||
if (access_ok(VERIFY_WRITE,
|
||||
(void *) arg, sizeof(struct serial_struct))) {
|
||||
ret = ec_tty_get_serial_info(t, (struct serial_struct *) arg);
|
||||
} else {
|
||||
@@ -513,9 +519,10 @@ static int ec_tty_ioctl(struct tty_struct *tty, struct file *file,
|
||||
/*****************************************************************************/
|
||||
|
||||
static void ec_tty_set_termios(struct tty_struct *tty,
|
||||
struct ktermios *old_termios)
|
||||
struct ktermios *old_termios)
|
||||
{
|
||||
//ec_tty_t *t = (ec_tty_t *) tty->driver_data;
|
||||
ec_tty_t *t = (ec_tty_t *) tty->driver_data;
|
||||
int ret;
|
||||
|
||||
#if EC_TTY_DEBUG >= 2
|
||||
printk(KERN_INFO PFX "%s().\n", __func__);
|
||||
@@ -528,6 +535,13 @@ static void ec_tty_set_termios(struct tty_struct *tty,
|
||||
printk(KERN_INFO "cflag changed from %x to %x.\n",
|
||||
old_termios->c_cflag, tty->termios->c_cflag);
|
||||
#endif
|
||||
|
||||
ret = t->cflag_cb(t->cb_data, tty->termios->c_cflag);
|
||||
if (ret) {
|
||||
printk(KERN_ERR PFX "ERROR: cflag 0x%x not accepted.\n",
|
||||
tty->termios->c_cflag);
|
||||
tty->termios->c_cflag = old_termios->c_cflag;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -598,25 +612,25 @@ static const struct tty_operations ec_tty_ops = {
|
||||
.open = ec_tty_open,
|
||||
.close = ec_tty_close,
|
||||
.write = ec_tty_write,
|
||||
.put_char = ec_tty_put_char,
|
||||
.write_room = ec_tty_write_room,
|
||||
.chars_in_buffer = ec_tty_chars_in_buffer,
|
||||
.flush_buffer = ec_tty_flush_buffer,
|
||||
.ioctl = ec_tty_ioctl,
|
||||
.set_termios = ec_tty_set_termios,
|
||||
.stop = ec_tty_stop,
|
||||
.start = ec_tty_start,
|
||||
.hangup = ec_tty_hangup,
|
||||
.break_ctl = ec_tty_break,
|
||||
.send_xchar = ec_tty_send_xchar,
|
||||
.wait_until_sent = ec_tty_wait_until_sent,
|
||||
.put_char = ec_tty_put_char,
|
||||
.write_room = ec_tty_write_room,
|
||||
.chars_in_buffer = ec_tty_chars_in_buffer,
|
||||
.flush_buffer = ec_tty_flush_buffer,
|
||||
.ioctl = ec_tty_ioctl,
|
||||
.set_termios = ec_tty_set_termios,
|
||||
.stop = ec_tty_stop,
|
||||
.start = ec_tty_start,
|
||||
.hangup = ec_tty_hangup,
|
||||
.break_ctl = ec_tty_break,
|
||||
.send_xchar = ec_tty_send_xchar,
|
||||
.wait_until_sent = ec_tty_wait_until_sent,
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* Public functions and methods
|
||||
*****************************************************************************/
|
||||
|
||||
ec_tty_t *ectty_create(void)
|
||||
ec_tty_t *ectty_create(int (*cflag_cb)(void *, unsigned short), void *cb_data)
|
||||
{
|
||||
ec_tty_t *tty;
|
||||
int minor, ret;
|
||||
@@ -636,7 +650,7 @@ ec_tty_t *ectty_create(void)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
ret = ec_tty_init(tty, minor);
|
||||
ret = ec_tty_init(tty, minor, cflag_cb, cb_data);
|
||||
if (ret) {
|
||||
up(&tty_sem);
|
||||
kfree(tty);
|
||||
|
||||
Reference in New Issue
Block a user