2 * Linux CAN-bus device driver.
3 * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
4 * Rewritten for new CAN queues by Pavel Pisa - OCERA team member
5 * email:pisa@cmp.felk.cvut.cz
6 * This software is released under the GPL-License.
7 * Version lincan-0.3 17 Jun 2004
10 #include "../include/can.h"
11 #include "../include/can_sysdep.h"
12 #include "../include/main.h"
13 #include "../include/write.h"
15 ssize_t can_write(struct file *file, const char *buffer, size_t length, loff_t *offset)
17 struct canuser_t *canuser = (struct canuser_t*)(file->private_data);
19 struct canmsg_t msg_buff;
20 struct canque_ends_t *qends;
21 struct canque_edge_t *qedge;
22 struct canque_slot_t *slot;
24 unsigned bytes_to_copy;
26 if(!canuser || (canuser->magic != CAN_USER_MAGIC)){
27 CANMSG("can_write: bad canuser magic\n");
31 if (length < sizeof(struct canmsg_t)) {
32 DEBUGMSG("Trying to write less bytes than a CAN message,\n");
33 DEBUGMSG("this will always return 0 !\n");
36 if (length > INT_MAX) {
37 CANMSG("Trying to write more than is supported.\n");
40 if (length % sizeof(struct canmsg_t)) {
41 CANMSG("The number of bytes requested to be written is not a multiple of\n");
42 CANMSG("'sizeof(struct canmsg_t)', currently this is not allowed.\n");
46 /* Initialize hardware pointers */
47 obj = canuser->msgobj;
49 CANMSG("Could not assign buffer structure\n");
52 qends = canuser->qends;
55 /* Prepare first message */
56 ret = copy_from_user(&msg_buff, buffer, sizeof(struct canmsg_t));
57 if(ret) return -EFAULT;
59 /* Automatic selection of extended format if ID>2047 */
60 if (msg_buff.id & ~0x7ffl & MSG_ID_MASK ) msg_buff.flags |= MSG_EXT;
61 /* has been dependent on "extended" option */
63 /* If the output buffer is full, return immediately in case O_NONBLOCK
64 * has been specified or loop until space becomes available.
66 if ((ret=canque_get_inslot4id(qends, &qedge, &slot,
67 0, msg_buff.id, 0))<0){
68 DEBUGMSG("Buffer is full\n");
72 if (file->f_flags & O_NONBLOCK)
75 ret=canque_get_inslot4id_wait_kern(qends, &qedge, &slot,
78 if (signal_pending(current))
85 canque_put_inslot(qends, qedge, slot);
86 buffer += sizeof(struct canmsg_t);
87 bytes_to_copy = length-sizeof(struct canmsg_t);
90 * Try to send more messages
92 while (bytes_to_copy >= sizeof(struct canmsg_t)) {
93 bytes_to_copy -= sizeof(struct canmsg_t);
94 /* Prepare first message */
95 ret = copy_from_user(&msg_buff, buffer, sizeof(struct canmsg_t));
96 if(ret) return -EFAULT;
98 /* Automatic selection of extended format if ID>2047 */
99 if (msg_buff.id & ~0x7ffl & MSG_ID_MASK ) msg_buff.flags |= MSG_EXT;
100 /* has been dependent on "extended" option */
103 if(canque_get_inslot4id(qends, &qedge, &slot,
104 0, msg_buff.id, 0) < 0) break;
106 canque_put_inslot(qends, qedge, slot);
107 buffer += sizeof(struct canmsg_t);
110 if(file->f_flags & O_SYNC) {
111 canque_sync_wait_kern(qends, qedge);
113 return length-bytes_to_copy;