Module: xenomai-gch
Branch: for-forge
Commit: 055d4b1b554bc4f1a056e24e3fc74ed4a833e72d
URL:    
http://git.xenomai.org/?p=xenomai-gch.git;a=commit;h=055d4b1b554bc4f1a056e24e3fc74ed4a833e72d

Author: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org>
Date:   Thu Dec 26 22:20:27 2013 +0100

cobalt/fd: add read/write/ioctl operations

---

 include/cobalt/kernel/fd.h |   14 ++++++++-
 kernel/cobalt/fd.c         |   68 ++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 75 insertions(+), 7 deletions(-)

diff --git a/include/cobalt/kernel/fd.h b/include/cobalt/kernel/fd.h
index 54ef678..bb8d94d 100644
--- a/include/cobalt/kernel/fd.h
+++ b/include/cobalt/kernel/fd.h
@@ -19,14 +19,26 @@
 #ifndef _COBALT_KERNEL_FD_H
 #define _COBALT_KERNEL_FD_H
 
+#include <linux/types.h>
+
 struct xnfd;
 struct xnselector;
 struct xnsys_ppd;
 
+typedef int xnfd_ioctl_t(struct xnfd *fd, unsigned int request, void __user 
*arg);
+typedef ssize_t xnfd_read_t(struct xnfd *fd, void __user *buf, size_t size);
+typedef ssize_t xnfd_write_t(struct xnfd *fd, const void __user *buf, size_t 
size);
+
 struct xnfd_ops {
-       void (*destroy)(struct xnfd *fd);
+       xnfd_ioctl_t *ioctl_rt;
+       xnfd_ioctl_t *ioctl_nrt;
+       xnfd_read_t *read_rt;
+       xnfd_read_t *read_nrt;
+       xnfd_write_t *write_rt;
+       xnfd_write_t *write_nrt;
        int (*select_bind)(struct xnfd *fd, struct xnselector *selector,
                        unsigned type, unsigned index);
+       void (*destroy)(struct xnfd *fd);
 };
 
 struct xnfd {
diff --git a/kernel/cobalt/fd.c b/kernel/cobalt/fd.c
index 19d4569..ebc0af6 100644
--- a/kernel/cobalt/fd.c
+++ b/kernel/cobalt/fd.c
@@ -49,17 +49,67 @@ static struct xnfd *xnfd_hash_search(int ufd, struct 
mm_struct *mm)
        return NULL;
 }
 
+static int enosys(void)
+{
+       return -ENOSYS;
+}
+
+static int ebadf(void)
+{
+       return -EBADF;
+}
+
+static void nop_destroy(struct xnfd *xnfd)
+{
+}
+
 int xnfd_enter(struct xnfd *xnfd, unsigned magic, int ufd, 
        struct xnsys_ppd *p, struct xnfd_ops *ops)
 {
        unsigned bucket;
        spl_t s;
+       int err;
 
-       if (magic == 0)
-               return -EINVAL;
+       if (magic == 0) {
+               err = -EINVAL;
+               goto err;
+       }
+
+       if (ops->ioctl_rt == NULL && ops->ioctl_nrt == NULL)
+               ops->ioctl_rt = ops->ioctl_nrt = (xnfd_ioctl_t *)ebadf;
+       else {
+               if (ops->ioctl_rt == NULL)
+                       ops->ioctl_rt = (xnfd_ioctl_t *)enosys;
+               if (ops->ioctl_nrt == NULL)
+                       ops->ioctl_nrt = (xnfd_ioctl_t *)enosys;
+       }
+
+       if (ops->read_rt == NULL && ops->read_nrt == NULL)
+               ops->read_rt = ops->read_nrt = (xnfd_read_t *)ebadf;
+       else {
+               if (ops->read_rt == NULL)
+                       ops->read_rt = (xnfd_read_t *)enosys;
+               if (ops->read_nrt == NULL)
+                       ops->read_nrt = (xnfd_read_t *)enosys;
+       }
+
+       if (ops->write_rt == NULL && ops->write_nrt == NULL)
+               ops->write_rt = ops->write_nrt = (xnfd_write_t *)ebadf;
+       else {
+               if (ops->write_rt == NULL)
+                       ops->write_rt = (xnfd_write_t *)enosys;
+               if (ops->write_nrt == NULL)
+                       ops->write_nrt = (xnfd_write_t *)enosys;
+       }
+
+       if (ops->select_bind == NULL)
+               ops->select_bind = (typeof(ops->select_bind))ebadf;
+
+       if (ops->destroy == NULL)
+               ops->destroy = nop_destroy;
 
        xnfd->magic = magic;
-       xnfd->mm = p != &__xnsys_global_ppd ? p->ppd.key.mm : NULL;
+       xnfd->mm = p != &__xnsys_global_ppd ? p->ppd.key.mm : &init_mm;
        xnfd->ufd = ufd;
        xnfd->refs = 1;
        xnfd->ops = ops;
@@ -69,7 +119,8 @@ int xnfd_enter(struct xnfd *xnfd, unsigned magic, int ufd,
 #if XENO_DEBUG(NUCLEUS)
        if (xnfd_hash_search(ufd, xnfd->mm)) {
                xnlock_put_irqrestore(&xnfd_lock, s);
-               return -EBUSY;
+               err = -EBUSY;
+               goto err;
        }
 #endif
        hlist_add_head(&xnfd->hlink, &xnfd_hash[bucket]);
@@ -77,6 +128,11 @@ int xnfd_enter(struct xnfd *xnfd, unsigned magic, int ufd,
        xnlock_put_irqrestore(&xnfd_lock, s);
        
        return 0;
+
+  err:
+       if (ops->destroy)
+               ops->destroy(xnfd);
+       return err;
 }
 
 struct xnfd *xnfd_get(int ufd, struct mm_struct *mm, unsigned magic)
@@ -86,7 +142,7 @@ struct xnfd *xnfd_get(int ufd, struct mm_struct *mm, 
unsigned magic)
        
        xnlock_get_irqsave(&xnfd_lock, s);
        res = xnfd_hash_search(ufd, mm);
-       if (res == NULL || res->magic != magic) {
+       if (res == NULL || (magic && res->magic != magic)) {
                res = ERR_PTR(-EBADF);
                goto err_unlock;
        }
@@ -138,7 +194,7 @@ int xnfd_close(int ufd, struct mm_struct *mm, unsigned 
magic)
        
        xnlock_get_irqsave(&xnfd_lock, s);
        xnfd = xnfd_hash_search(ufd, mm);
-       if (xnfd == NULL || xnfd->magic != magic) {
+       if (xnfd == NULL || (magic && xnfd->magic != magic)) {
                xnlock_put_irqrestore(&xnfd_lock, s);
                return -EBADF;
        }


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to