]> rtime.felk.cvut.cz Git - lincan.git/blobdiff - lincan/src/write_rtl.c
Added full RT-Linux POSIX interface to LinCAN driver, needs preparation of RT tests.
[lincan.git] / lincan / src / write_rtl.c
diff --git a/lincan/src/write_rtl.c b/lincan/src/write_rtl.c
new file mode 100644 (file)
index 0000000..a1d4647
--- /dev/null
@@ -0,0 +1,101 @@
+/* write.c
+ * Linux CAN-bus device driver.
+ * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
+ * Rewritten for new CAN queues by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.2  9 Jul 2003
+ */
+
+#ifdef CAN_WITH_RTL
+
+#include "../include/can.h"
+#include "../include/can_sysdep.h"
+#include "../include/main.h"
+
+#include <rtl_posixio.h>
+#include "../include/can_iortl.h"
+
+ssize_t can_write_rtl_posix(struct rtl_file *fptr, const char *buffer,
+                                size_t length, loff_t *ppos)
+{
+       struct canuser_t *canuser =
+               (struct canuser_t *)can_get_rtl_file_private_data(fptr);
+       const struct canmsg_t *msg_buff = (struct canmsg_t *)buffer;
+       struct canque_ends_t *qends;
+       struct canque_edge_t *qedge;
+       struct canque_slot_t *slot;
+       int      msg_flags;
+       int      ret;
+       size_t   bytes_to_copy;
+
+       if(!canuser || (canuser->magic != CAN_USER_MAGIC)){
+               CANMSG("can_write_rtl_posix: bad canuser magic\n");
+               return -ENODEV;
+       }
+
+       if (length < sizeof(struct canmsg_t)) {
+               DEBUGMSG("Trying to write less bytes than a CAN message,\n");
+               DEBUGMSG("this will always return 0 !\n");
+               return 0;
+       }
+       if (length > INT_MAX) {
+               CANMSG("Trying to write more than is supported.\n");
+               return -1;
+       }
+
+       qends = canuser->qends;
+
+       msg_flags=msg_buff->flags;
+       /* Automatic selection of extended format if "extended" set and ID>2047 */
+       if (extended) if (msg_buff->id & ~0x7ffl ) msg_flags |= MSG_EXT;
+
+       /* If the output buffer is full, return immediately in case O_NONBLOCK
+        * has been specified or loop until space becomes available.
+        */
+       if ((ret=canque_get_inslot4id(qends, &qedge, &slot, 
+                       0, msg_buff->id, 0))<0){
+               DEBUGMSG("Buffer is full\n");
+               if(ret < -1)
+                       return -EIO;
+
+               if (fptr->f_flags & O_NONBLOCK)
+                       return -EAGAIN;
+
+               ret=canque_get_inslot4id_wait_rtl(qends, &qedge, &slot, 
+                                               0, msg_buff->id, 0);
+               if (ret == -1)
+                       return -EINTR;
+               
+               if(ret<0) {
+                       return -EIO;
+               }
+       }
+       slot->msg=*(msg_buff++);
+       slot->msg.flags=msg_flags;
+       canque_put_inslot(qends, qedge, slot);
+       bytes_to_copy = length-sizeof(struct canmsg_t);
+
+       /* 
+        * Try to send more messages
+        */
+       while (bytes_to_copy >= sizeof(struct canmsg_t)) {
+               bytes_to_copy -= sizeof(struct canmsg_t);
+               msg_flags=msg_buff->flags;
+               /* Automatic selection of extended format if "extended" set and ID>2047 */
+               if (extended) if (msg_buff->id & ~0x7ffl ) msg_flags |= MSG_EXT;
+               /* Get slot */
+               if(canque_get_inslot4id(qends, &qedge, &slot, 
+                       0, msg_buff->id, 0) < 0) break;
+               slot->msg=*(msg_buff++);
+               slot->msg.flags=msg_flags;
+               canque_put_inslot(qends, qedge, slot);
+       }
+
+        if(fptr->f_flags & O_SYNC) {
+               canque_sync_wait_rtl(qends, qedge);
+       }
+       return length-bytes_to_copy;
+}      
+
+#endif /*CAN_WITH_RTL*/