summaryrefslogtreecommitdiffstats
path: root/cpukit/libcsupport/src/termios.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-09-16 12:58:06 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-09-19 07:52:33 +0200
commit55e0be36069942e0343e406615a3b1744cf7d6b3 (patch)
treea260825ed4914c1e96683924bfaa04a00bc50e8b /cpukit/libcsupport/src/termios.c
parentlibtests/devfs: Use printk() (diff)
downloadrtems-55e0be36069942e0343e406615a3b1744cf7d6b3.tar.bz2
termios: Use IMFS nodes for new Termios devices
This makes the new Termios devices independent of device major/minor numbers. It enables BSP independent Termios device drivers which may reside in the cpukit domain. These drivers require an IMFS and do not work with the device file system. However, the device file system should go away in the future.
Diffstat (limited to 'cpukit/libcsupport/src/termios.c')
-rw-r--r--cpukit/libcsupport/src/termios.c460
1 files changed, 277 insertions, 183 deletions
diff --git a/cpukit/libcsupport/src/termios.c b/cpukit/libcsupport/src/termios.c
index d9886f4c01..3a6a3897f4 100644
--- a/cpukit/libcsupport/src/termios.c
+++ b/cpukit/libcsupport/src/termios.c
@@ -22,6 +22,8 @@
#include <rtems.h>
#include <rtems/libio.h>
+#include <rtems/imfs.h>
+#include <rtems/score/assert.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
@@ -85,6 +87,8 @@ static size_t rtems_termios_cbufsize = 256;
static size_t rtems_termios_raw_input_size = 128;
static size_t rtems_termios_raw_output_size = 64;
+static const IMFS_node_control rtems_termios_imfs_node_control;
+
static struct rtems_termios_tty *rtems_termios_ttyHead;
static struct rtems_termios_tty *rtems_termios_ttyTail;
@@ -108,126 +112,55 @@ static rtems_task rtems_termios_txdaemon(rtems_task_argument argument);
#define TERMIOS_RX_PROC_EVENT RTEMS_EVENT_1
#define TERMIOS_RX_TERMINATE_EVENT RTEMS_EVENT_0
-static rtems_termios_device_node *
-rtems_termios_find_device_node(
- rtems_device_major_number major,
- rtems_device_minor_number minor
-)
+static rtems_status_code
+rtems_termios_obtain (void)
{
- rtems_chain_node *tail = rtems_chain_tail(&rtems_termios_devices);
- rtems_chain_node *current = rtems_chain_first(&rtems_termios_devices);
-
- while (current != tail) {
- rtems_termios_device_node *device_node =
- (rtems_termios_device_node *) current;
-
- if (device_node->major == major && device_node->minor == minor) {
- return device_node;
- }
+ return rtems_semaphore_obtain (rtems_termios_ttyMutex, RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT);
+}
- current = rtems_chain_next(current);
- }
+static void
+rtems_termios_release (void)
+{
+ rtems_status_code sc;
- return NULL;
+ sc = rtems_semaphore_release (rtems_termios_ttyMutex);
+ _Assert (sc == RTEMS_SUCCESSFUL);
+ (void) sc;
}
rtems_status_code rtems_termios_device_install(
const char *device_file,
- rtems_device_major_number major,
- rtems_device_minor_number minor,
const rtems_termios_device_handler *handler,
const rtems_termios_device_flow *flow,
rtems_termios_device_context *context
)
{
- rtems_status_code sc;
rtems_termios_device_node *new_device_node;
- rtems_termios_device_node *existing_device_node;
+ int rv;
- new_device_node = malloc(sizeof(*new_device_node));
+ new_device_node = calloc (1, sizeof(*new_device_node));
if (new_device_node == NULL) {
return RTEMS_NO_MEMORY;
}
- rtems_chain_initialize_node(&new_device_node->node);
- new_device_node->major = major;
- new_device_node->minor = minor;
+ rtems_chain_initialize_node (&new_device_node->node);
new_device_node->handler = handler;
new_device_node->flow = flow;
new_device_node->context = context;
new_device_node->tty = NULL;
- sc = rtems_semaphore_obtain(
- rtems_termios_ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
- if (sc != RTEMS_SUCCESSFUL) {
- free(new_device_node);
- return RTEMS_INCORRECT_STATE;
- }
-
- existing_device_node = rtems_termios_find_device_node (major, minor);
- if (existing_device_node != NULL) {
- free(new_device_node);
- rtems_semaphore_release (rtems_termios_ttyMutex);
- return RTEMS_RESOURCE_IN_USE;
- }
-
- if (device_file != NULL) {
- sc = rtems_io_register_name (device_file, major, minor);
- if (sc != RTEMS_SUCCESSFUL) {
- free(new_device_node);
- rtems_semaphore_release (rtems_termios_ttyMutex);
- return RTEMS_UNSATISFIED;
- }
- }
-
- rtems_chain_append_unprotected(
- &rtems_termios_devices, &new_device_node->node);
-
- rtems_semaphore_release (rtems_termios_ttyMutex);
-
- return RTEMS_SUCCESSFUL;
-}
-
-rtems_status_code rtems_termios_device_remove(
- const char *device_file,
- rtems_device_major_number major,
- rtems_device_minor_number minor
-)
-{
- rtems_status_code sc;
- rtems_termios_device_node *device_node;
-
- sc = rtems_semaphore_obtain(
- rtems_termios_ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
- if (sc != RTEMS_SUCCESSFUL) {
- return RTEMS_INCORRECT_STATE;
- }
-
- device_node = rtems_termios_find_device_node (major, minor);
- if (device_node == NULL) {
- rtems_semaphore_release (rtems_termios_ttyMutex);
- return RTEMS_INVALID_ID;
- }
-
- if (device_node->tty != NULL) {
- rtems_semaphore_release (rtems_termios_ttyMutex);
- return RTEMS_RESOURCE_IN_USE;
- }
-
- if (device_file != NULL) {
- int rv = unlink (device_file);
-
- if (rv != 0) {
- rtems_semaphore_release (rtems_termios_ttyMutex);
- return RTEMS_UNSATISFIED;
- }
+ rv = IMFS_make_generic_node(
+ device_file,
+ S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
+ &rtems_termios_imfs_node_control,
+ new_device_node
+ );
+ if (rv != 0) {
+ free (new_device_node);
+ return RTEMS_UNSATISFIED;
}
- rtems_chain_extract_unprotected (&device_node->node);
- free (device_node);
-
- rtems_semaphore_release (rtems_termios_ttyMutex);
-
return RTEMS_SUCCESSFUL;
}
@@ -629,40 +562,6 @@ rtems_termios_open_tty(
return tty;
}
-rtems_status_code
-rtems_termios_device_open(
- rtems_device_major_number major,
- rtems_device_minor_number minor,
- void *arg
-)
-{
- rtems_status_code sc;
- rtems_termios_device_node *device_node;
- struct rtems_termios_tty *tty;
-
- sc = rtems_semaphore_obtain(
- rtems_termios_ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
- if (sc != RTEMS_SUCCESSFUL)
- return sc;
-
- device_node = rtems_termios_find_device_node (major, minor);
- if (device_node == NULL) {
- rtems_semaphore_release (rtems_termios_ttyMutex);
- return RTEMS_INVALID_ID;
- }
-
- tty = rtems_termios_open_tty(
- major, minor, arg, device_node->tty, device_node, NULL);
- if (tty == NULL) {
- rtems_semaphore_release (rtems_termios_ttyMutex);
- return RTEMS_NO_MEMORY;
- }
-
- rtems_semaphore_release (rtems_termios_ttyMutex);
-
- return RTEMS_SUCCESSFUL;
-}
-
/*
* Open a termios device
*/
@@ -680,8 +579,7 @@ rtems_termios_open (
/*
* See if the device has already been opened
*/
- sc = rtems_semaphore_obtain(
- rtems_termios_ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ sc = rtems_termios_obtain ();
if (sc != RTEMS_SUCCESSFUL)
return sc;
@@ -693,7 +591,7 @@ rtems_termios_open (
tty = rtems_termios_open_tty(
major, minor, arg, tty, NULL, callbacks);
if (tty == NULL) {
- rtems_semaphore_release (rtems_termios_ttyMutex);
+ rtems_termios_release ();
return RTEMS_NO_MEMORY;
}
@@ -710,7 +608,7 @@ rtems_termios_open (
rtems_termios_ttyTail = tty;
}
- rtems_semaphore_release (rtems_termios_ttyMutex);
+ rtems_termios_release ();
return RTEMS_SUCCESSFUL;
}
@@ -755,8 +653,7 @@ rtems_termios_close (void *arg)
rtems_libio_open_close_args_t *args = arg;
struct rtems_termios_tty *tty = args->iop->data1;
- sc = rtems_semaphore_obtain(
- rtems_termios_ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ sc = rtems_termios_obtain ();
if (sc != RTEMS_SUCCESSFUL)
rtems_fatal_error_occurred (sc);
@@ -782,26 +679,7 @@ rtems_termios_close (void *arg)
rtems_termios_close_tty (tty, arg);
- rtems_semaphore_release (rtems_termios_ttyMutex);
-
- return RTEMS_SUCCESSFUL;
-}
-
-rtems_status_code
-rtems_termios_device_close (void *arg)
-{
- rtems_status_code sc;
- rtems_libio_open_close_args_t *args = arg;
- struct rtems_termios_tty *tty = args->iop->data1;
-
- sc = rtems_semaphore_obtain(
- rtems_termios_ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
- if (sc != RTEMS_SUCCESSFUL)
- rtems_fatal_error_occurred (sc);
-
- rtems_termios_close_tty (tty, arg);
-
- rtems_semaphore_release (rtems_termios_ttyMutex);
+ rtems_termios_release ();
return RTEMS_SUCCESSFUL;
}
@@ -1193,6 +1071,25 @@ oproc (unsigned char c, struct rtems_termios_tty *tty)
rtems_termios_puts (&c, 1, tty);
}
+static uint32_t
+rtems_termios_write_tty (struct rtems_termios_tty *tty, const char *buffer,
+ uint32_t initial_count)
+{
+
+ if (tty->termios.c_oflag & OPOST) {
+ uint32_t count;
+
+ count = initial_count;
+
+ while (count--)
+ oproc (*buffer++, tty);
+ } else {
+ rtems_termios_puts (buffer, initial_count, tty);
+ }
+
+ return initial_count;
+}
+
rtems_status_code
rtems_termios_write (void *arg)
{
@@ -1208,16 +1105,7 @@ rtems_termios_write (void *arg)
rtems_semaphore_release (tty->osem);
return sc;
}
- if (tty->termios.c_oflag & OPOST) {
- uint32_t count = args->count;
- char *buffer = args->buffer;
- while (count--)
- oproc (*buffer++, tty);
- args->bytes_moved = args->count;
- } else {
- rtems_termios_puts (args->buffer, args->count, tty);
- args->bytes_moved = args->count;
- }
+ args->bytes_moved = rtems_termios_write_tty (tty, args->buffer, args->count);
rtems_semaphore_release (tty->osem);
return sc;
}
@@ -1521,27 +1409,17 @@ fillBufferQueue (struct rtems_termios_tty *tty)
return RTEMS_SUCCESSFUL;
}
-rtems_status_code
-rtems_termios_read (void *arg)
+static uint32_t
+rtems_termios_read_tty (struct rtems_termios_tty *tty, char *buffer,
+ uint32_t initial_count)
{
- rtems_libio_rw_args_t *args = arg;
- struct rtems_termios_tty *tty = args->iop->data1;
- uint32_t count = args->count;
- char *buffer = args->buffer;
- rtems_status_code sc;
-
- sc = rtems_semaphore_obtain (tty->isem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
- if (sc != RTEMS_SUCCESSFUL)
- return sc;
+ uint32_t count;
- if (rtems_termios_linesw[tty->t_line].l_read != NULL) {
- sc = rtems_termios_linesw[tty->t_line].l_read(tty,args);
- tty->tty_rcvwakeup = 0;
- rtems_semaphore_release (tty->isem);
- return sc;
- }
+ count = initial_count;
if (tty->cindex == tty->ccount) {
+ rtems_status_code sc;
+
tty->cindex = tty->ccount = 0;
tty->read_start_column = tty->column;
if (tty->handler.poll_read != NULL && tty->handler.mode == TERMIOS_POLLED)
@@ -1556,8 +1434,29 @@ rtems_termios_read (void *arg)
*buffer++ = tty->cbuf[tty->cindex++];
count--;
}
- args->bytes_moved = args->count - count;
tty->tty_rcvwakeup = 0;
+ return initial_count - count;
+}
+
+rtems_status_code
+rtems_termios_read (void *arg)
+{
+ rtems_libio_rw_args_t *args = arg;
+ struct rtems_termios_tty *tty = args->iop->data1;
+ rtems_status_code sc;
+
+ sc = rtems_semaphore_obtain (tty->isem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ return sc;
+
+ if (rtems_termios_linesw[tty->t_line].l_read != NULL) {
+ sc = rtems_termios_linesw[tty->t_line].l_read(tty,args);
+ tty->tty_rcvwakeup = 0;
+ rtems_semaphore_release (tty->isem);
+ return sc;
+ }
+
+ args->bytes_moved = rtems_termios_read_tty (tty, args->buffer, args->count);
rtems_semaphore_release (tty->isem);
return sc;
}
@@ -1928,3 +1827,198 @@ static rtems_task rtems_termios_rxdaemon(rtems_task_argument argument)
}
}
}
+
+static int
+rtems_termios_imfs_open (rtems_libio_t *iop,
+ const char *path, int oflag, mode_t mode)
+{
+ rtems_termios_device_node *device_node;
+ rtems_status_code sc;
+ rtems_libio_open_close_args_t args;
+ struct rtems_termios_tty *tty;
+
+ device_node = IMFS_generic_get_context_by_iop (iop);
+
+ memset (&args, 0, sizeof (args));
+ args.iop = iop;
+ args.flags = iop->flags;
+ args.mode = mode;
+
+ sc = rtems_termios_obtain ();
+ if (sc != RTEMS_SUCCESSFUL) {
+ rtems_set_errno_and_return_minus_one (ENXIO);
+ }
+
+ tty = rtems_termios_open_tty (device_node->major, device_node->minor, &args,
+ device_node->tty, device_node, NULL);
+ if (tty == NULL) {
+ rtems_termios_release ();
+ rtems_set_errno_and_return_minus_one (ENOMEM);
+ }
+
+ rtems_termios_release ();
+ return 0;
+}
+
+static int
+rtems_termios_imfs_close (rtems_libio_t *iop)
+{
+ rtems_status_code sc;
+ rtems_libio_open_close_args_t args;
+ struct rtems_termios_tty *tty;
+
+ memset (&args, 0, sizeof (args));
+ args.iop = iop;
+
+ tty = iop->data1;
+
+ sc = rtems_termios_obtain ();
+ _Assert (sc == RTEMS_SUCCESSFUL);
+ (void) sc;
+
+ rtems_termios_close_tty (tty, &args);
+ rtems_termios_release ();
+ return 0;
+}
+
+static ssize_t
+rtems_termios_imfs_read (rtems_libio_t *iop, void *buffer, size_t count)
+{
+ struct rtems_termios_tty *tty;
+ rtems_status_code sc;
+ uint32_t bytes_moved;
+
+ tty = iop->data1;
+
+ sc = rtems_semaphore_obtain (tty->isem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ _Assert (sc == RTEMS_SUCCESSFUL);
+
+ if (rtems_termios_linesw[tty->t_line].l_read != NULL) {
+ rtems_libio_rw_args_t args;
+
+ memset (&args, 0, sizeof (args));
+ args.iop = iop;
+ args.buffer = buffer;
+ args.count = count;
+ args.flags = iop->flags;
+
+ sc = rtems_termios_linesw[tty->t_line].l_read (tty, &args);
+ tty->tty_rcvwakeup = 0;
+ rtems_semaphore_release (tty->isem);
+
+ if (sc != RTEMS_SUCCESSFUL) {
+ return rtems_status_code_to_errno (sc);
+ }
+
+ return (ssize_t) args.bytes_moved;
+ }
+
+ bytes_moved = rtems_termios_read_tty (tty, buffer, count);
+ rtems_semaphore_release (tty->isem);
+ return (ssize_t) bytes_moved;
+}
+
+static ssize_t
+rtems_termios_imfs_write (rtems_libio_t *iop, const void *buffer, size_t count)
+{
+ struct rtems_termios_tty *tty;
+ rtems_status_code sc;
+ uint32_t bytes_moved;
+
+ tty = iop->data1;
+
+ sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ _Assert (sc == RTEMS_SUCCESSFUL);
+
+ if (rtems_termios_linesw[tty->t_line].l_write != NULL) {
+ rtems_libio_rw_args_t args;
+
+ memset (&args, 0, sizeof (args));
+ args.iop = iop;
+ args.buffer = RTEMS_DECONST (void *, buffer);
+ args.count = count;
+ args.flags = iop->flags;
+
+ sc = rtems_termios_linesw[tty->t_line].l_write (tty, &args);
+ rtems_semaphore_release (tty->osem);
+
+ if (sc != RTEMS_SUCCESSFUL) {
+ return rtems_status_code_to_errno (sc);
+ }
+
+ return (ssize_t) args.bytes_moved;
+ }
+
+ bytes_moved = rtems_termios_write_tty (tty, buffer, count);
+ rtems_semaphore_release (tty->osem);
+ return (ssize_t) bytes_moved;
+}
+
+static int
+rtems_termios_imfs_ioctl (rtems_libio_t *iop, uint32_t request, void *buffer)
+{
+ rtems_status_code sc;
+ rtems_libio_ioctl_args_t args;
+
+ memset (&args, 0, sizeof (args));
+ args.iop = iop;
+ args.command = request;
+ args.buffer = buffer;
+
+ sc = rtems_termios_ioctl (&args);
+ if ( sc == RTEMS_SUCCESSFUL ) {
+ return args.ioctl_return;
+ } else {
+ return rtems_status_code_to_errno (sc);
+ }
+}
+
+static const rtems_filesystem_file_handlers_r rtems_termios_imfs_handler = {
+ .open_h = rtems_termios_imfs_open,
+ .close_h = rtems_termios_imfs_close,
+ .read_h = rtems_termios_imfs_read,
+ .write_h = rtems_termios_imfs_write,
+ .ioctl_h = rtems_termios_imfs_ioctl,
+ .lseek_h = rtems_filesystem_default_lseek,
+ .fstat_h = IMFS_stat,
+ .ftruncate_h = rtems_filesystem_default_ftruncate,
+ .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
+ .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
+ .fcntl_h = rtems_filesystem_default_fcntl,
+ .kqfilter_h = rtems_filesystem_default_kqfilter,
+ .poll_h = rtems_filesystem_default_poll,
+ .readv_h = rtems_filesystem_default_readv,
+ .writev_h = rtems_filesystem_default_writev
+};
+
+static IMFS_jnode_t *
+rtems_termios_imfs_node_initialize (IMFS_jnode_t *node, void *arg)
+{
+ rtems_termios_device_node *device_node;
+ dev_t dev;
+
+ node = IMFS_node_initialize_generic (node, arg);
+ device_node = IMFS_generic_get_context_by_node (node);
+ dev = IMFS_generic_get_device_identifier_by_node (node);
+ device_node->major = rtems_filesystem_dev_major_t (dev);
+ device_node->minor = rtems_filesystem_dev_minor_t (dev);
+
+ return node;
+}
+
+static void
+rtems_termios_imfs_node_destroy (IMFS_jnode_t *node)
+{
+ rtems_termios_device_node *device_node;
+
+ device_node = IMFS_generic_get_context_by_node (node);
+ free (device_node);
+ IMFS_node_destroy_default (node);
+}
+
+static const IMFS_node_control rtems_termios_imfs_node_control =
+ IMFS_GENERIC_INITIALIZER(
+ &rtems_termios_imfs_handler,
+ rtems_termios_imfs_node_initialize,
+ rtems_termios_imfs_node_destroy
+ );