]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/read.c
b1798974bc43c948b7185a7fefe67e6e267dbdf5
[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         init_waitqueue_head(&new_rtr_entry->rtr_wq);
102         new_rtr_entry->id = read_msg.id;
103         new_rtr_entry->rtr_message = &read_msg;
104         new_rtr_entry->next=NULL;
105
106         spin_unlock_irqrestore(&hardware_p->rtr_lock, flags);
107
108         /* Send remote transmission request */
109         chip->chipspecops->remote_request(chip,obj);
110         obj->ret = 0;
111         interruptible_sleep_on(&new_rtr_entry->rtr_wq);
112
113         spin_lock_irqsave(&hardware_p->rtr_lock, flags);
114         copy_to_user(buffer, &read_msg, sizeof(struct canmsg_t));
115         if (hardware_p->rtr_queue == new_rtr_entry) {
116                 if (new_rtr_entry->next != NULL) 
117                         hardware_p->rtr_queue=new_rtr_entry->next;
118                 else
119                         hardware_p->rtr_queue=NULL;
120         }
121         else {
122                 rtr_current=hardware_p->rtr_queue;
123                 while (rtr_current->next != new_rtr_entry)
124                         rtr_current=rtr_current->next;
125                 if (new_rtr_entry->next != NULL)
126                         rtr_current->next=new_rtr_entry->next;
127                 else
128                         rtr_current->next=NULL;
129         }
130         spin_unlock_irqrestore(&hardware_p->rtr_lock, flags);
131         kfree(new_rtr_entry);
132
133         return obj->ret;
134 }
135
136 ssize_t can_read(struct file *file, char *buffer, size_t length, loff_t *offset)
137 {
138         struct canuser_t *canuser = (struct canuser_t*)(file->private_data);
139         struct msgobj_t *obj;
140         struct chip_t *chip;
141         struct canmsg_t read_msg;
142         struct canque_ends_t *qends;
143         int ret=0;
144
145         if(!canuser || (canuser->magic != CAN_USER_MAGIC)){
146                 CANMSG("can_close: bad canuser magic\n");
147                 return -ENODEV;
148         }
149
150         if (length < sizeof(struct canmsg_t)) {
151                 DEBUGMSG("Trying to read less bytes than a CAN message, \n");
152                 DEBUGMSG("this will always return zero.\n");
153                 return 0;
154         }
155         /* Initialize hardware pointers */
156         obj = canuser->msgobj;
157         if (obj == NULL) {
158                 CANMSG("Could not assign buffer structure\n");
159                 return -1;
160         }
161         qends = canuser->qends;
162         if ( (chip = obj->hostchip) == NULL) {
163                 CANMSG("Device is not correctly configured,\n");
164                 CANMSG("please reload the driver.\n");
165                 return -1;
166         }
167
168         copy_from_user(&read_msg, buffer, sizeof(struct canmsg_t));
169         if (read_msg.flags & MSG_RTR)
170                 ret = can_rtr_read(chip, obj, buffer);
171         else
172                 ret = can_std_read(file, qends, obj, buffer, length);
173
174         return ret;
175 }
176
177