Structured comments updated.
[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 #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         can_spin_lock_irqsave(&hardware_p->rtr_lock, flags);
72         if (hardware_p->rtr_queue == NULL) { //No remote messages pending
73                 new_rtr_entry=(struct rtr_id *)kmalloc(sizeof(struct rtr_id),GFP_ATOMIC);
74                 if (new_rtr_entry == NULL) {
75                         can_spin_unlock_irqrestore(&hardware_p->rtr_lock, 
76                                                                 flags);
77                         return -ENOMEM;
78                 }
79                 hardware_p->rtr_queue=new_rtr_entry;
80         }
81         else {
82                 rtr_current=hardware_p->rtr_queue;
83                 while (rtr_current->next != NULL)
84                         rtr_current=rtr_current->next;
85                 new_rtr_entry=(struct rtr_id *)kmalloc(sizeof(struct rtr_id),GFP_ATOMIC);
86                 rtr_current->next=new_rtr_entry;
87         }
88         init_waitqueue_head(&new_rtr_entry->rtr_wq);
89         new_rtr_entry->id = read_msg.id;
90         new_rtr_entry->rtr_message = &read_msg;
91         new_rtr_entry->next=NULL;
92
93         can_spin_unlock_irqrestore(&hardware_p->rtr_lock, flags);
94
95         /* Send remote transmission request */
96         chip->chipspecops->remote_request(chip,obj);
97         obj->ret = 0;
98         interruptible_sleep_on(&new_rtr_entry->rtr_wq);
99
100         can_spin_lock_irqsave(&hardware_p->rtr_lock, flags);
101         copy_to_user(buffer, &read_msg, sizeof(struct canmsg_t));
102         if (hardware_p->rtr_queue == new_rtr_entry) {
103                 if (new_rtr_entry->next != NULL) 
104                         hardware_p->rtr_queue=new_rtr_entry->next;
105                 else
106                         hardware_p->rtr_queue=NULL;
107         }
108         else {
109                 rtr_current=hardware_p->rtr_queue;
110                 while (rtr_current->next != new_rtr_entry)
111                         rtr_current=rtr_current->next;
112                 if (new_rtr_entry->next != NULL)
113                         rtr_current->next=new_rtr_entry->next;
114                 else
115                         rtr_current->next=NULL;
116         }
117         can_spin_unlock_irqrestore(&hardware_p->rtr_lock, flags);
118         kfree(new_rtr_entry);
119
120         return obj->ret;
121 }
122
123 ssize_t can_read(struct file *file, char *buffer, size_t length, loff_t *offset)
124 {
125         struct canuser_t *canuser = (struct canuser_t*)(file->private_data);
126         struct msgobj_t *obj;
127         struct chip_t *chip;
128         struct canmsg_t read_msg;
129         struct canque_ends_t *qends;
130         int ret=0;
131
132         if(!canuser || (canuser->magic != CAN_USER_MAGIC)){
133                 CANMSG("can_read: bad canuser magic\n");
134                 return -ENODEV;
135         }
136
137         if (length < sizeof(struct canmsg_t)) {
138                 DEBUGMSG("Trying to read less bytes than a CAN message, \n");
139                 DEBUGMSG("this will always return zero.\n");
140                 return 0;
141         }
142         /* Initialize hardware pointers */
143         obj = canuser->msgobj;
144         if (obj == NULL) {
145                 CANMSG("Could not assign buffer structure\n");
146                 return -1;
147         }
148         qends = canuser->qends;
149         if ( (chip = obj->hostchip) == NULL) {
150                 CANMSG("Device is not correctly configured,\n");
151                 CANMSG("please reload the driver.\n");
152                 return -1;
153         }
154
155         copy_from_user(&read_msg, buffer, sizeof(struct canmsg_t));
156         if (read_msg.flags & MSG_RTR)
157                 ret = can_rtr_read(chip, obj, buffer);
158         else
159                 ret = can_std_read(file, qends, obj, buffer, length);
160
161         return ret;
162 }
163
164