2 * Linux CAN-bus device driver.
3 * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
4 * This software is released under the GPL-License.
5 * Version 0.7 6 Aug 2001
8 #include <linux/autoconf.h>
9 #if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS)
13 #if defined (MODVERSIONS)
14 #include <linux/modversions.h>
17 #define __NO_VERSION__
18 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <linux/sched.h>
21 #include <linux/delay.h>
23 #include <asm/uaccess.h>
25 #include "../include/main.h"
27 ssize_t can_write(struct file *file, const char *buffer, size_t length, loff_t *offset)
31 struct canmsg_t *write_msg;
32 struct canfifo_t *fifo;
36 int bytes_to_copy = 0;
39 if (length < sizeof(struct canmsg_t)) {
40 DEBUGMSG("Trying to write less bytes than a CAN message,\n");
41 DEBUGMSG("this will always return 0 !\n");
44 if (length > 8 * sizeof(struct canmsg_t)) {
45 CANMSG("Trying to write more than is supported.\n");
48 if (length % sizeof(struct canmsg_t)) {
49 CANMSG("The number of bytes requested to be written is not a multiple of\n");
50 CANMSG("'sizeof(struct canmsg_t)', currently this is not allowed.\n");
54 /* Initialize hardware pointers */
55 if ( (obj = objects_p[MINOR_NR]) == NULL) {
56 CANMSG("Could not assign buffer structure\n");
59 if ( (chip = obj->hostchip) == NULL) {
60 CANMSG("Device is not correctly configured,\n");
61 CANMSG("please reload the driver\n");
64 if ( (fifo = obj->fifo) == NULL) {
65 CANMSG("Could not assign buffer memory\n");
69 /* Initialize pointer to the first message to be sent */
70 write_msg = fifo->tx_writep;
72 /* Calculate free buffer space */
74 space = ((int)fifo->tx_writep < (int)fifo->tx_readp) ?
75 ((int)fifo->tx_readp - (int)fifo->tx_writep) :
76 ((int)fifo->tx_readp - (int)fifo->tx_writep +
80 /* If the output buffer is full, return immediately in case O_NONBLOCK
81 * has been specified or loop until space becomes available.
83 while (space < sizeof(struct canmsg_t)) {
84 DEBUGMSG("Buffer is full\n");
85 if (file->f_flags & O_NONBLOCK)
87 can_timeout = interruptible_sleep_on_timeout(&fifo->writeq,
89 if (signal_pending(current))
94 space = ((int)fifo->tx_writep < (int)fifo->tx_readp) ?
95 ((int)fifo->tx_readp - (int)fifo->tx_writep) :
96 ((int)fifo->tx_readp - (int)fifo->tx_writep +
101 /* There's space available in the kernel output buffer.
102 * Find out wich is smaller: 'length', the number of bytes requested to
103 * be written or 'space', the number of bytes available in the kernel
104 * buffer. We copy the least of the two to kernel space.
106 // space = space - (space % sizeof(struct canmsg_t)); // round it
107 bytes_to_copy = space < length ? space : length;
108 copy_from_user(fifo->tx_writep, buffer, bytes_to_copy);
109 written = bytes_to_copy;
110 while (bytes_to_copy > 0) {
112 if (fifo->tx_writep >= fifo->buf_tx_entry + MAX_BUF_LENGTH)
113 fifo->tx_writep = fifo->buf_tx_entry;
114 bytes_to_copy -= sizeof(struct canmsg_t);
117 /* Copy the data to be transmitted into the output buffer */
118 /* while ( (written < length) && (space >= sizeof(struct canmsg_t)) ) {
119 copy_from_user(fifo->tx_writep,buffer, sizeof(struct canmsg_t));
122 if (fifo->tx_writep >= fifo->buf_tx_entry + MAX_BUF_LENGTH)
123 fifo->tx_writep = fifo->buf_tx_entry;
124 buffer += sizeof(struct canmsg_t);
125 written += sizeof(struct canmsg_t);
126 space = ((int)fifo->tx_writep < (int)fifo->tx_readp) ?
127 ((int)fifo->tx_readp - (int)fifo->tx_writep) :
128 ((int)fifo->tx_readp - (int)fifo->tx_writep +
133 /* Initiate transmission in case we are not already transmitting */
135 if (!fifo->tx_in_progress) {
136 fifo->tx_in_progress = 1;
138 if ( (ret = chip->chipspecops->pre_write_config(chip, obj,
140 CANMSG("Error initializing hardware for sending\n");
144 if ( (ret = chip->chipspecops->send_msg(chip, obj,
146 CANMSG("Error sending message\n");
149 /* If O_SYNC is specified wait for successfull transmission */
152 if ( (!file->f_flags & O_SYNC) ||
153 (!fifo->tx_in_progress)) {
161 if (fifo->tx_in_progress) {
162 can_timeout = interruptible_sleep_on_timeout(
163 &fifo->writeq, CANTIMEOUT);
166 if (signal_pending(current))