]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/read.c
64b24155723cd1ecdc92bc13c9933a9de15e750b
[lincan.git] / lincan / src / read.c
1 /* read.c
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.2  9 Jul 2003
8  */
9
10 #define __NO_VERSION__
11 #include <linux/module.h> 
12
13 #include <linux/autoconf.h>
14
15 #include <linux/version.h>
16 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
17 #include <linux/malloc.h>
18 #else
19 #include <linux/slab.h>
20 #endif
21 #include <linux/version.h>
22 #include <asm/uaccess.h>
23 #include <asm/irq.h>
24
25 #include "../include/main.h"
26 #include "../include/read.h"
27 #include "../include/ioctl.h"
28
29 /* This is the 'Normal' read handler for normal transmission messages */
30 inline ssize_t can_std_read(struct file *file, struct canque_ends_t *qends, 
31                         struct msgobj_t *obj, char *buffer, size_t length)
32 {
33         int ret;
34         int bytes_to_copy;
35         struct canque_edge_t *qedge;
36         struct canque_slot_t *slot;
37         
38         ret=canque_test_outslot(qends, &qedge, &slot);
39         if(ret<0){
40                 if (file->f_flags & O_NONBLOCK) {
41                         return -EAGAIN;
42                 }
43                 ret=canque_get_outslot_wait_kern(qends, &qedge, &slot);
44                 if(ret<0){
45                         if (signal_pending(current)) {
46                                 DEBUGMSG("Rx interrupted\n");
47                                 return -EINTR;
48                         }
49                         /*if (!can_timeout) {
50                                 DEBUGMSG("no data received\n");
51                                 return 0;
52                         }*/
53                         return -EIO;
54                 }
55         }
56         
57         copy_to_user(buffer, &slot->msg, sizeof(struct canmsg_t));
58         canque_free_outslot(qends, qedge, slot);
59         buffer += sizeof(struct canmsg_t);
60         bytes_to_copy = length-sizeof(struct canmsg_t);
61         
62         while (bytes_to_copy > 0) {
63                 ret=canque_test_outslot(qends, &qedge, &slot);
64                 if(ret<0)
65                         break;
66                 copy_to_user(buffer, &slot->msg, sizeof(struct canmsg_t));
67                 canque_free_outslot(qends, qedge, slot);
68                 buffer += sizeof(struct canmsg_t);
69                 bytes_to_copy -= sizeof(struct canmsg_t);
70         }
71
72         return length-bytes_to_copy;
73 }
74
75 /* This is the 'RTR' read handler for remote transmission request messages */
76 inline ssize_t can_rtr_read(struct chip_t *chip, struct msgobj_t *obj, 
77                                                                 char *buffer)
78 {
79         unsigned long flags;
80         struct rtr_id *rtr_current, *new_rtr_entry;
81         struct canmsg_t read_msg;
82         
83         DEBUGMSG("Remote transmission request\n");
84         spin_lock_irqsave(&hardware_p->rtr_lock, flags);
85         if (hardware_p->rtr_queue == NULL) { //No remote messages pending
86                 new_rtr_entry=(struct rtr_id *)kmalloc(sizeof(struct rtr_id),GFP_ATOMIC);
87                 if (new_rtr_entry == NULL) {
88                         spin_unlock_irqrestore(&hardware_p->rtr_lock, 
89                                                                 flags);
90                         return -ENOMEM;
91                 }
92                 hardware_p->rtr_queue=new_rtr_entry;
93         }
94         else {
95                 rtr_current=hardware_p->rtr_queue;
96                 while (rtr_current->next != NULL)
97                         rtr_current=rtr_current->next;
98                 new_rtr_entry=(struct rtr_id *)kmalloc(sizeof(struct rtr_id),GFP_ATOMIC);
99                 rtr_current->next=new_rtr_entry;
100         }
101 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
102         init_waitqueue(&new_rtr_entry->rtr_wq);
103 #else
104         init_waitqueue_head(&new_rtr_entry->rtr_wq);
105 #endif
106         new_rtr_entry->id = read_msg.id;
107         new_rtr_entry->rtr_message = &read_msg;
108         new_rtr_entry->next=NULL;
109
110         spin_unlock_irqrestore(&hardware_p->rtr_lock, flags);
111
112         /* Send remote transmission request */
113         chip->chipspecops->remote_request(chip,obj);
114         obj->ret = 0;
115         interruptible_sleep_on(&new_rtr_entry->rtr_wq);
116
117         spin_lock_irqsave(&hardware_p->rtr_lock, flags);
118         copy_to_user(buffer, &read_msg, sizeof(struct canmsg_t));
119         if (hardware_p->rtr_queue == new_rtr_entry) {
120                 if (new_rtr_entry->next != NULL) 
121                         hardware_p->rtr_queue=new_rtr_entry->next;
122                 else
123                         hardware_p->rtr_queue=NULL;
124         }
125         else {
126                 rtr_current=hardware_p->rtr_queue;
127                 while (rtr_current->next != new_rtr_entry)
128                         rtr_current=rtr_current->next;
129                 if (new_rtr_entry->next != NULL)
130                         rtr_current->next=new_rtr_entry->next;
131                 else
132                         rtr_current->next=NULL;
133         }
134         spin_unlock_irqrestore(&hardware_p->rtr_lock, flags);
135         kfree(new_rtr_entry);
136
137         return obj->ret;
138 }
139
140 ssize_t can_read(struct file *file, char *buffer, size_t length, loff_t *offset)
141 {
142         struct canuser_t *canuser = (struct canuser_t*)(file->private_data);
143         struct msgobj_t *obj;
144         struct chip_t *chip;
145         struct canmsg_t read_msg;
146         struct canque_ends_t *qends;
147         int ret=0;
148
149         if(!canuser || (canuser->magic != CAN_USER_MAGIC)){
150                 CANMSG("can_close: bad canuser magic\n");
151                 return -ENODEV;
152         }
153
154         if (length < sizeof(struct canmsg_t)) {
155                 DEBUGMSG("Trying to read less bytes than a CAN message, \n");
156                 DEBUGMSG("this will always return zero.\n");
157                 return 0;
158         }
159         if (length > 8 * sizeof(struct canmsg_t)) {
160                 DEBUGMSG("Reading more than 8 CAN messages, this is not supported.\n");
161                 DEBUGMSG("Defaulting to 8 messages.\n");
162                 length = 8 * sizeof(struct canmsg_t);
163         }
164         /* Initialize hardware pointers */
165         obj = canuser->msgobj;
166         if (obj == NULL) {
167                 CANMSG("Could not assign buffer structure\n");
168                 return -1;
169         }
170         qends = canuser->qends;
171         if ( (chip = obj->hostchip) == NULL) {
172                 CANMSG("Device is not correctly configured,\n");
173                 CANMSG("please reload the driver.\n");
174                 return -1;
175         }
176
177         copy_from_user(&read_msg, buffer, sizeof(struct canmsg_t));
178         if (read_msg.flags & MSG_RTR)
179                 ret = can_rtr_read(chip, obj, buffer);
180         else
181                 ret = can_std_read(file, qends, obj, buffer, length);
182
183         return ret;
184 }
185
186