Skip to content
Snippets Groups Projects
Commit a6090bc1 authored by Martin Troxler's avatar Martin Troxler
Browse files

Merged

parents dae74cd2 e847423a
No related branches found
No related tags found
No related merge requests found
This diff is collapsed.
...@@ -42,6 +42,8 @@ ...@@ -42,6 +42,8 @@
#ifndef __ECTTY_H__ #ifndef __ECTTY_H__
#define __ECTTY_H__ #define __ECTTY_H__
#include <linux/termios.h>
/****************************************************************************** /******************************************************************************
* Data types * Data types
*****************************************************************************/ *****************************************************************************/
...@@ -49,15 +51,29 @@ ...@@ -49,15 +51,29 @@
struct ec_tty; struct ec_tty;
typedef struct ec_tty ec_tty_t; /**< \see ec_tty */ typedef struct ec_tty ec_tty_t; /**< \see ec_tty */
/**
* \param cflag_changed This callback function is called when the serial
* settings shall be changed. The \a cflag argument contains the new settings.
*/
typedef struct {
int (*cflag_changed)(void *, tcflag_t);
} ec_tty_operations_t;
/****************************************************************************** /******************************************************************************
* Global functions * Global functions
*****************************************************************************/ *****************************************************************************/
/** Create a virtual TTY interface. /** Create a virtual TTY interface.
* *
* \param ops Set of callbacks.
* \param cb_data Arbitrary data, that is passed to any callback.
*
* \return Pointer to the interface object, otherwise an ERR_PTR value. * \return Pointer to the interface object, otherwise an ERR_PTR value.
*/ */
ec_tty_t *ectty_create(void); ec_tty_t *ectty_create(
const ec_tty_operations_t *ops,
void *cb_data
);
/****************************************************************************** /******************************************************************************
* TTY interface methods * TTY interface methods
......
...@@ -43,12 +43,15 @@ ...@@ -43,12 +43,15 @@
/** Maximum time in ms to wait for responses when reading out the dictionary. /** Maximum time in ms to wait for responses when reading out the dictionary.
*/ */
#define EC_FSM_COE_DICT_TIMEOUT 3000 #define EC_FSM_COE_DICT_TIMEOUT 1000
#define EC_COE_DOWN_REQ_HEADER_SIZE 10 #define EC_COE_DOWN_REQ_HEADER_SIZE 10
#define EC_COE_DOWN_SEG_REQ_HEADER_SIZE 3 #define EC_COE_DOWN_SEG_REQ_HEADER_SIZE 3
#define EC_COE_DOWN_SEG_MIN_DATA_SIZE 7 #define EC_COE_DOWN_SEG_MIN_DATA_SIZE 7
#define DEBUG_RETRIES 0
#define DEBUG_LONG 0
/*****************************************************************************/ /*****************************************************************************/
void ec_fsm_coe_dict_start(ec_fsm_coe_t *); void ec_fsm_coe_dict_start(ec_fsm_coe_t *);
...@@ -624,8 +627,9 @@ void ec_fsm_coe_dict_desc_check(ec_fsm_coe_t *fsm /**< finite state machine */) ...@@ -624,8 +627,9 @@ void ec_fsm_coe_dict_desc_check(ec_fsm_coe_t *fsm /**< finite state machine */)
(datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ; (datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ;
if (diff_ms >= EC_FSM_COE_DICT_TIMEOUT) { if (diff_ms >= EC_FSM_COE_DICT_TIMEOUT) {
fsm->state = ec_fsm_coe_error; fsm->state = ec_fsm_coe_error;
EC_ERR("Timeout while waiting for SDO object description " EC_ERR("Timeout while waiting for SDO 0x%04x object description "
"response on slave %u.\n", slave->ring_position); "response on slave %u.\n", fsm->sdo->index,
slave->ring_position);
return; return;
} }
...@@ -860,8 +864,9 @@ void ec_fsm_coe_dict_entry_check(ec_fsm_coe_t *fsm ...@@ -860,8 +864,9 @@ void ec_fsm_coe_dict_entry_check(ec_fsm_coe_t *fsm
(datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ; (datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ;
if (diff_ms >= EC_FSM_COE_DICT_TIMEOUT) { if (diff_ms >= EC_FSM_COE_DICT_TIMEOUT) {
fsm->state = ec_fsm_coe_error; fsm->state = ec_fsm_coe_error;
EC_ERR("Timeout while waiting for SDO entry description response " EC_ERR("Timeout while waiting for SDO entry 0x%04x:%x"
"on slave %u.\n", slave->ring_position); " description response on slave %u.\n",
fsm->sdo->index, fsm->subindex, slave->ring_position);
return; return;
} }
...@@ -1196,6 +1201,7 @@ void ec_fsm_coe_down_request(ec_fsm_coe_t *fsm /**< finite state machine */) ...@@ -1196,6 +1201,7 @@ void ec_fsm_coe_down_request(ec_fsm_coe_t *fsm /**< finite state machine */)
{ {
ec_datagram_t *datagram = fsm->datagram; ec_datagram_t *datagram = fsm->datagram;
ec_slave_t *slave = fsm->slave; ec_slave_t *slave = fsm->slave;
unsigned long diff_ms;
if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
return; // FIXME: check for response first? return; // FIXME: check for response first?
...@@ -1208,27 +1214,39 @@ void ec_fsm_coe_down_request(ec_fsm_coe_t *fsm /**< finite state machine */) ...@@ -1208,27 +1214,39 @@ void ec_fsm_coe_down_request(ec_fsm_coe_t *fsm /**< finite state machine */)
return; return;
} }
diff_ms = (jiffies - fsm->request->jiffies_sent) * 1000 / HZ;
if (datagram->working_counter != 1) { if (datagram->working_counter != 1) {
if (!datagram->working_counter) { if (!datagram->working_counter) {
unsigned long diff_ms =
(jiffies - fsm->request->jiffies_sent) * 1000 / HZ;
if (diff_ms < fsm->request->response_timeout) { if (diff_ms < fsm->request->response_timeout) {
#if DEBUG_RETRIES
if (fsm->slave->master->debug_level) { if (fsm->slave->master->debug_level) {
EC_DBG("Slave %u did not respond to SDO download request. " EC_DBG("Slave %u did not respond to SDO download request. "
"Retrying after %u ms...\n", "Retrying after %u ms...\n",
slave->ring_position, (u32) diff_ms); slave->ring_position, (u32) diff_ms);
} }
#endif
// no response; send request datagram again // no response; send request datagram again
return; return;
} }
} }
fsm->state = ec_fsm_coe_error; fsm->state = ec_fsm_coe_error;
EC_ERR("Reception of CoE download request failed on slave %u: ", EC_ERR("Reception of CoE download request for SDO 0x%04x:%x failed"
slave->ring_position); " with timeout after %u ms on slave %u: ",
fsm->request->index, fsm->request->subindex, (u32) diff_ms,
fsm->slave->ring_position);
ec_datagram_print_wc_error(datagram); ec_datagram_print_wc_error(datagram);
return; return;
} }
#if DEBUG_LONG
if (diff_ms > 200) {
EC_WARN("SDO 0x%04x:%x download took %u ms on slave %u.\n",
fsm->request->index, fsm->request->subindex, (u32) diff_ms,
fsm->slave->ring_position);
}
#endif
fsm->jiffies_start = datagram->jiffies_sent; fsm->jiffies_start = datagram->jiffies_sent;
ec_slave_mbox_prepare_check(slave, datagram); // can not fail. ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
...@@ -1271,8 +1289,10 @@ void ec_fsm_coe_down_check(ec_fsm_coe_t *fsm /**< finite state machine */) ...@@ -1271,8 +1289,10 @@ void ec_fsm_coe_down_check(ec_fsm_coe_t *fsm /**< finite state machine */)
(datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ; (datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ;
if (diff_ms >= fsm->request->response_timeout) { if (diff_ms >= fsm->request->response_timeout) {
fsm->state = ec_fsm_coe_error; fsm->state = ec_fsm_coe_error;
EC_ERR("Timeout while waiting for SDO download response on " EC_ERR("Timeout after %u ms while waiting for SDO 0x%04x:%x"
"slave %u.\n", slave->ring_position); " download response on slave %u.\n", (u32) diff_ms,
fsm->request->index, fsm->request->subindex,
slave->ring_position);
return; return;
} }
...@@ -1689,6 +1709,7 @@ void ec_fsm_coe_up_request(ec_fsm_coe_t *fsm /**< finite state machine */) ...@@ -1689,6 +1709,7 @@ void ec_fsm_coe_up_request(ec_fsm_coe_t *fsm /**< finite state machine */)
{ {
ec_datagram_t *datagram = fsm->datagram; ec_datagram_t *datagram = fsm->datagram;
ec_slave_t *slave = fsm->slave; ec_slave_t *slave = fsm->slave;
unsigned long diff_ms;
if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
return; // FIXME: check for response first? return; // FIXME: check for response first?
...@@ -1701,27 +1722,39 @@ void ec_fsm_coe_up_request(ec_fsm_coe_t *fsm /**< finite state machine */) ...@@ -1701,27 +1722,39 @@ void ec_fsm_coe_up_request(ec_fsm_coe_t *fsm /**< finite state machine */)
return; return;
} }
diff_ms = (jiffies - fsm->request->jiffies_sent) * 1000 / HZ;
if (datagram->working_counter != 1) { if (datagram->working_counter != 1) {
if (!datagram->working_counter) { if (!datagram->working_counter) {
unsigned long diff_ms =
(jiffies - fsm->request->jiffies_sent) * 1000 / HZ;
if (diff_ms < fsm->request->response_timeout) { if (diff_ms < fsm->request->response_timeout) {
#if DEBUG_RETRIES
if (fsm->slave->master->debug_level) { if (fsm->slave->master->debug_level) {
EC_DBG("Slave %u did not respond to SDO upload request. " EC_DBG("Slave %u did not respond to SDO upload request. "
"Retrying after %u ms...\n", "Retrying after %u ms...\n",
slave->ring_position, (u32) diff_ms); slave->ring_position, (u32) diff_ms);
} }
#endif
// no response; send request datagram again // no response; send request datagram again
return; return;
} }
} }
fsm->state = ec_fsm_coe_error; fsm->state = ec_fsm_coe_error;
EC_ERR("Reception of CoE upload request failed on slave %u: ", EC_ERR("Reception of CoE upload request for SDO 0x%04x:%x failed"
slave->ring_position); " with timeout after %u ms on slave %u: ",
fsm->request->index, fsm->request->subindex, (u32) diff_ms,
fsm->slave->ring_position);
ec_datagram_print_wc_error(datagram); ec_datagram_print_wc_error(datagram);
return; return;
} }
#if DEBUG_LONG
if (diff_ms > 200) {
EC_WARN("SDO 0x%04x:%x upload took %u ms on slave %u.\n",
fsm->request->index, fsm->request->subindex, (u32) diff_ms,
fsm->slave->ring_position);
}
#endif
fsm->jiffies_start = datagram->jiffies_sent; fsm->jiffies_start = datagram->jiffies_sent;
ec_slave_mbox_prepare_check(slave, datagram); // can not fail. ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
...@@ -1764,8 +1797,10 @@ void ec_fsm_coe_up_check(ec_fsm_coe_t *fsm /**< finite state machine */) ...@@ -1764,8 +1797,10 @@ void ec_fsm_coe_up_check(ec_fsm_coe_t *fsm /**< finite state machine */)
(datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ; (datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ;
if (diff_ms >= fsm->request->response_timeout) { if (diff_ms >= fsm->request->response_timeout) {
fsm->state = ec_fsm_coe_error; fsm->state = ec_fsm_coe_error;
EC_ERR("Timeout while waiting for SDO upload response on " EC_ERR("Timeout after %u ms while waiting for SDO 0x%04x:%x"
"slave %u.\n", slave->ring_position); " upload response on slave %u.\n", (u32) diff_ms,
fsm->request->index, fsm->request->subindex,
slave->ring_position);
return; return;
} }
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
/** Default timeout in ms to wait for SDO transfer responses. /** Default timeout in ms to wait for SDO transfer responses.
*/ */
#define EC_SDO_REQUEST_RESPONSE_TIMEOUT 3000 #define EC_SDO_REQUEST_RESPONSE_TIMEOUT 1000
/*****************************************************************************/ /*****************************************************************************/
......
...@@ -49,6 +49,7 @@ MODPROBE=/sbin/modprobe ...@@ -49,6 +49,7 @@ MODPROBE=/sbin/modprobe
RMMOD=/sbin/rmmod RMMOD=/sbin/rmmod
MODINFO=/sbin/modinfo MODINFO=/sbin/modinfo
ETHERCAT=@prefix@/bin/ethercat ETHERCAT=@prefix@/bin/ethercat
MASTER_ARGS=
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
...@@ -162,7 +163,7 @@ start) ...@@ -162,7 +163,7 @@ start)
done done
# load master module # load master module
if ! ${MODPROBE} ${MODPROBE_FLAGS} ec_master \ if ! ${MODPROBE} ${MODPROBE_FLAGS} ec_master ${MASTER_ARGS} \
main_devices=${DEVICES} backup_devices=${BACKUPS}; then main_devices=${DEVICES} backup_devices=${BACKUPS}; then
exit_fail exit_fail
fi fi
......
...@@ -41,6 +41,8 @@ ...@@ -41,6 +41,8 @@
#include <linux/termios.h> #include <linux/termios.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/version.h> #include <linux/version.h>
#include <linux/serial.h>
#include <linux/uaccess.h>
#include "../master/globals.h" #include "../master/globals.h"
#include "../include/ectty.h" #include "../include/ectty.h"
...@@ -49,7 +51,7 @@ ...@@ -49,7 +51,7 @@
#define PFX "ec_tty: " #define PFX "ec_tty: "
#define EC_TTY_MAX_DEVICES 10 #define EC_TTY_MAX_DEVICES 32
#define EC_TTY_TX_BUFFER_SIZE 100 #define EC_TTY_TX_BUFFER_SIZE 100
#define EC_TTY_RX_BUFFER_SIZE 100 #define EC_TTY_RX_BUFFER_SIZE 100
...@@ -64,6 +66,8 @@ static struct tty_driver *tty_driver = NULL; ...@@ -64,6 +66,8 @@ static struct tty_driver *tty_driver = NULL;
ec_tty_t *ttys[EC_TTY_MAX_DEVICES]; ec_tty_t *ttys[EC_TTY_MAX_DEVICES];
struct semaphore tty_sem; struct semaphore tty_sem;
void ec_tty_wakeup(unsigned long);
/*****************************************************************************/ /*****************************************************************************/
/** \cond */ /** \cond */
...@@ -78,11 +82,15 @@ MODULE_PARM_DESC(debug_level, "Debug level"); ...@@ -78,11 +82,15 @@ MODULE_PARM_DESC(debug_level, "Debug level");
/** \endcond */ /** \endcond */
/** Standard termios for ec_tty devices.
*
* Simplest possible configuration, as you would expect.
*/
static struct ktermios ec_tty_std_termios = { static struct ktermios ec_tty_std_termios = {
.c_iflag = ICRNL | IXON, .c_iflag = 0,
.c_oflag = OPOST, .c_oflag = 0,
.c_cflag = B38400 | CS8 | CREAD | HUPCL, .c_cflag = B9600 | CS8 | CREAD,
.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN, .c_lflag = 0,
.c_cc = INIT_C_CC, .c_cc = INIT_C_CC,
}; };
...@@ -101,6 +109,9 @@ struct ec_tty { ...@@ -101,6 +109,9 @@ struct ec_tty {
struct timer_list timer; struct timer_list timer;
struct tty_struct *tty; struct tty_struct *tty;
ec_tty_operations_t ops;
void *cb_data;
}; };
static const struct tty_operations ec_tty_ops; // see below static const struct tty_operations ec_tty_ops; // see below
...@@ -139,7 +150,6 @@ int __init ec_tty_init_module(void) ...@@ -139,7 +150,6 @@ int __init ec_tty_init_module(void)
tty_driver->subtype = SERIAL_TYPE_NORMAL; tty_driver->subtype = SERIAL_TYPE_NORMAL;
tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
tty_driver->init_termios = ec_tty_std_termios; tty_driver->init_termios = ec_tty_std_termios;
tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
tty_set_operations(tty_driver, &ec_tty_ops); tty_set_operations(tty_driver, &ec_tty_ops);
ret = tty_register_driver(tty_driver); ret = tty_register_driver(tty_driver);
...@@ -169,6 +179,65 @@ void __exit ec_tty_cleanup_module(void) ...@@ -169,6 +179,65 @@ void __exit ec_tty_cleanup_module(void)
printk(KERN_INFO PFX "Module unloading.\n"); printk(KERN_INFO PFX "Module unloading.\n");
} }
/******************************************************************************
* ec_tty_t methods.
*****************************************************************************/
int ec_tty_init(ec_tty_t *t, int minor,
const ec_tty_operations_t *ops, void *cb_data)
{
int ret;
tcflag_t cflag;
struct tty_struct *tty;
t->minor = minor;
t->tx_read_idx = 0;
t->tx_write_idx = 0;
t->wakeup = 0;
t->rx_read_idx = 0;
t->rx_write_idx = 0;
init_timer(&t->timer);
t->tty = NULL;
t->ops = *ops;
t->cb_data = cb_data;
t->dev = tty_register_device(tty_driver, t->minor, NULL);
if (IS_ERR(t->dev)) {
printk(KERN_ERR PFX "Failed to register tty device.\n");
return PTR_ERR(t->dev);
}
// Tell the device-specific implementation about the initial cflags
tty = tty_driver->ttys[minor];
if (tty && tty->termios) { // already opened before
cflag = tty->termios->c_cflag;
} else {
cflag = tty_driver->init_termios.c_cflag;
}
ret = t->ops.cflag_changed(t->cb_data, cflag);
if (ret) {
printk(KERN_ERR PFX "ERROR: Initial cflag 0x%x not accepted.\n",
cflag);
tty_unregister_device(tty_driver, t->minor);
return ret;
}
t->timer.function = ec_tty_wakeup;
t->timer.data = (unsigned long) t;
t->timer.expires = jiffies + 10;
add_timer(&t->timer);
return 0;
}
/*****************************************************************************/
void ec_tty_clear(ec_tty_t *tty)
{
del_timer_sync(&tty->timer);
tty_unregister_device(tty_driver, tty->minor);
}
/*****************************************************************************/ /*****************************************************************************/
unsigned int ec_tty_tx_size(ec_tty_t *tty) unsigned int ec_tty_tx_size(ec_tty_t *tty)
...@@ -215,6 +284,25 @@ unsigned int ec_tty_rx_space(ec_tty_t *tty) ...@@ -215,6 +284,25 @@ unsigned int ec_tty_rx_space(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;
memset(&tmp, 0, sizeof(tmp));
if (copy_to_user(data, &tmp, sizeof(*data))) {
return -EFAULT;
}
return 0;
}
/*****************************************************************************/
/** Timer function.
*/
void ec_tty_wakeup(unsigned long data) void ec_tty_wakeup(unsigned long data)
{ {
ec_tty_t *tty = (ec_tty_t *) data; ec_tty_t *tty = (ec_tty_t *) data;
...@@ -237,10 +325,10 @@ void ec_tty_wakeup(unsigned long data) ...@@ -237,10 +325,10 @@ void ec_tty_wakeup(unsigned long data)
unsigned char *cbuf; unsigned char *cbuf;
int space = tty_prepare_flip_string(tty->tty, &cbuf, to_recv); int space = tty_prepare_flip_string(tty->tty, &cbuf, to_recv);
if (space < to_recv) { if (space < to_recv) {
printk(KERN_WARNING PFX "Insufficient space to_recv=%d space=%d\n", printk(KERN_WARNING PFX "Insufficient space to_recv=%d space=%d\n",
to_recv, space); to_recv, space);
} }
if (space < 0) { if (space < 0) {
to_recv = 0; to_recv = 0;
...@@ -257,50 +345,17 @@ void ec_tty_wakeup(unsigned long data) ...@@ -257,50 +345,17 @@ void ec_tty_wakeup(unsigned long data)
for (i = 0; i < to_recv; i++) { for (i = 0; i < to_recv; i++) {
cbuf[i] = tty->rx_buffer[tty->rx_read_idx]; cbuf[i] = tty->rx_buffer[tty->rx_read_idx];
tty->rx_read_idx = (tty->rx_read_idx + 1) % EC_TTY_RX_BUFFER_SIZE; tty->rx_read_idx =
(tty->rx_read_idx + 1) % EC_TTY_RX_BUFFER_SIZE;
} }
tty_flip_buffer_push(tty->tty); tty_flip_buffer_push(tty->tty);
} }
} }
tty->timer.expires += 1; tty->timer.expires += 1;
add_timer(&tty->timer); add_timer(&tty->timer);
} }
/*****************************************************************************/
int ec_tty_init(ec_tty_t *tty, int minor)
{
tty->minor = minor;
tty->tx_read_idx = 0;
tty->tx_write_idx = 0;
tty->wakeup = 0;
tty->rx_read_idx = 0;
tty->rx_write_idx = 0;
init_timer(&tty->timer);
tty->tty = NULL;
tty->dev = tty_register_device(tty_driver, tty->minor, NULL);
if (IS_ERR(tty->dev)) {
printk(KERN_ERR PFX "Failed to register tty device.\n");
return PTR_ERR(tty->dev);
}
tty->timer.function = ec_tty_wakeup;
tty->timer.data = (unsigned long) tty;
tty->timer.expires = jiffies + 10;
add_timer(&tty->timer);
return 0;
}
/*****************************************************************************/
void ec_tty_clear(ec_tty_t *tty)
{
del_timer_sync(&tty->timer);
tty_unregister_device(tty_driver, tty->minor);
}
/****************************************************************************** /******************************************************************************
* Device callbacks * Device callbacks
*****************************************************************************/ *****************************************************************************/
...@@ -314,8 +369,8 @@ static int ec_tty_open(struct tty_struct *tty, struct file *file) ...@@ -314,8 +369,8 @@ static int ec_tty_open(struct tty_struct *tty, struct file *file)
printk(KERN_INFO PFX "Opening line %i.\n", line); printk(KERN_INFO PFX "Opening line %i.\n", line);
#endif #endif
if (line < 0 || line >= EC_TTY_MAX_DEVICES) { if (line < 0 || line >= EC_TTY_MAX_DEVICES) {
return -ENXIO; return -ENXIO;
} }
t = ttys[line]; t = ttys[line];
...@@ -447,45 +502,75 @@ static void ec_tty_flush_buffer(struct tty_struct *tty) ...@@ -447,45 +502,75 @@ static void ec_tty_flush_buffer(struct tty_struct *tty)
#if EC_TTY_DEBUG >= 2 #if EC_TTY_DEBUG >= 2
printk(KERN_INFO PFX "%s().\n", __func__); printk(KERN_INFO PFX "%s().\n", __func__);
#endif #endif
// FIXME empty ring buffer
} }
/*****************************************************************************/ /*****************************************************************************/
static int ec_tty_ioctl(struct tty_struct *tty, struct file *file, 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;
#if EC_TTY_DEBUG >= 2 #if EC_TTY_DEBUG >= 2
printk(KERN_INFO PFX "%s().\n", __func__); printk(KERN_INFO PFX "%s(tty=%p, file=%p, cmd=%08x, arg=%08lx).\n",
__func__, tty, file, cmd, arg);
printk(KERN_INFO PFX "decoded: type=%02x nr=%u\n",
_IOC_TYPE(cmd), _IOC_NR(cmd));
#endif #endif
return -ENOTTY;
}
/*****************************************************************************/ switch (cmd) {
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 {
ret = -EFAULT;
}
break;
static void ec_tty_throttle(struct tty_struct *tty) case TIOCSSERIAL: // TODO
{ break;
default:
#if EC_TTY_DEBUG >= 2 #if EC_TTY_DEBUG >= 2
printk(KERN_INFO PFX "%s().\n", __func__); printk(KERN_INFO PFX "no ioctl() -> handled by tty core!\n");
#endif #endif
ret = -ENOIOCTLCMD;
break;
}
return ret;
} }
/*****************************************************************************/ /*****************************************************************************/
static void ec_tty_unthrottle(struct tty_struct *tty) static void ec_tty_set_termios(struct tty_struct *tty,
struct ktermios *old_termios)
{ {
ec_tty_t *t = (ec_tty_t *) tty->driver_data;
int ret;
#if EC_TTY_DEBUG >= 2 #if EC_TTY_DEBUG >= 2
printk(KERN_INFO PFX "%s().\n", __func__); printk(KERN_INFO PFX "%s().\n", __func__);
#endif #endif
}
/*****************************************************************************/ if (tty->termios->c_cflag == old_termios->c_cflag)
return;
static void ec_tty_set_termios(struct tty_struct *tty,
struct ktermios *old_termios)
{
#if EC_TTY_DEBUG >= 2 #if EC_TTY_DEBUG >= 2
printk(KERN_INFO PFX "%s().\n", __func__); printk(KERN_INFO "cflag changed from %x to %x.\n",
old_termios->c_cflag, tty->termios->c_cflag);
#endif #endif
ret = t->ops.cflag_changed(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;
}
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -552,54 +637,29 @@ static void ec_tty_wait_until_sent(struct tty_struct *tty, int timeout) ...@@ -552,54 +637,29 @@ static void ec_tty_wait_until_sent(struct tty_struct *tty, int timeout)
/*****************************************************************************/ /*****************************************************************************/
static int ec_tty_tiocmget(struct tty_struct *tty, struct file *file)
{
#if EC_TTY_DEBUG >= 2
printk(KERN_INFO PFX "%s().\n", __func__);
#endif
return -EBUSY;
}
/*****************************************************************************/
static int ec_tty_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
#if EC_TTY_DEBUG >= 2
printk(KERN_INFO PFX "%s(set=%u, clear=%u).\n", __func__, set, clear);
#endif
return -EBUSY;
}
/*****************************************************************************/
static const struct tty_operations ec_tty_ops = { static const struct tty_operations ec_tty_ops = {
.open = ec_tty_open, .open = ec_tty_open,
.close = ec_tty_close, .close = ec_tty_close,
.write = ec_tty_write, .write = ec_tty_write,
.put_char = ec_tty_put_char, .put_char = ec_tty_put_char,
.write_room = ec_tty_write_room, .write_room = ec_tty_write_room,
.chars_in_buffer = ec_tty_chars_in_buffer, .chars_in_buffer = ec_tty_chars_in_buffer,
.flush_buffer = ec_tty_flush_buffer, .flush_buffer = ec_tty_flush_buffer,
.ioctl = ec_tty_ioctl, .ioctl = ec_tty_ioctl,
.throttle = ec_tty_throttle, .set_termios = ec_tty_set_termios,
.unthrottle = ec_tty_unthrottle, .stop = ec_tty_stop,
.set_termios = ec_tty_set_termios, .start = ec_tty_start,
.stop = ec_tty_stop, .hangup = ec_tty_hangup,
.start = ec_tty_start, .break_ctl = ec_tty_break,
.hangup = ec_tty_hangup, .send_xchar = ec_tty_send_xchar,
.break_ctl = ec_tty_break, .wait_until_sent = ec_tty_wait_until_sent,
.send_xchar = ec_tty_send_xchar,
.wait_until_sent = ec_tty_wait_until_sent,
.tiocmget = ec_tty_tiocmget,
.tiocmset = ec_tty_tiocmset,
}; };
/****************************************************************************** /******************************************************************************
* Public functions and methods * Public functions and methods
*****************************************************************************/ *****************************************************************************/
ec_tty_t *ectty_create(void) ec_tty_t *ectty_create(const ec_tty_operations_t *ops, void *cb_data)
{ {
ec_tty_t *tty; ec_tty_t *tty;
int minor, ret; int minor, ret;
...@@ -619,7 +679,7 @@ ec_tty_t *ectty_create(void) ...@@ -619,7 +679,7 @@ ec_tty_t *ectty_create(void)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
ret = ec_tty_init(tty, minor); ret = ec_tty_init(tty, minor, ops, cb_data);
if (ret) { if (ret) {
up(&tty_sem); up(&tty_sem);
kfree(tty); kfree(tty);
...@@ -693,7 +753,8 @@ void ectty_rx_data(ec_tty_t *tty, const uint8_t *buffer, size_t size) ...@@ -693,7 +753,8 @@ void ectty_rx_data(ec_tty_t *tty, const uint8_t *buffer, size_t size)
for (i = 0; i < size; i++) { for (i = 0; i < size; i++) {
tty->rx_buffer[tty->rx_write_idx] = buffer[i]; tty->rx_buffer[tty->rx_write_idx] = buffer[i];
tty->rx_write_idx = (tty->rx_write_idx + 1) % EC_TTY_RX_BUFFER_SIZE; tty->rx_write_idx =
(tty->rx_write_idx + 1) % EC_TTY_RX_BUFFER_SIZE;
} }
} }
} }
......
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