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