fixing end of scan events in some drivers
[comedi.git] / comedi / drivers / comedi_fc.c
1 /*
2     cfc.c
3
4     This is a place for code driver writers wish to share between
5     two or more drivers.  cfc is short
6     for comedi-frank-common.
7
8     Author:  Frank Mori Hess <fmhess@users.sourceforge.net>
9     Copyright (C) 2002 Frank Mori Hess
10
11     This program is free software; you can redistribute it and/or modify
12     it under the terms of the GNU General Public License as published by
13     the Free Software Foundation; either version 2 of the License, or
14     (at your option) any later version.
15
16     This program is distributed in the hope that it will be useful,
17     but WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19     GNU General Public License for more details.
20
21     You should have received a copy of the GNU General Public License
22     along with this program; if not, write to the Free Software
23     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24
25 ************************************************************************/
26
27 #include <linux/module.h>
28 #include <linux/kernel.h>
29 #include "comedi_fc.h"
30
31 static inline unsigned int bytes_per_sample( comedi_subdevice *subd )
32 {
33         if( subd->flags & SDF_LSAMPL )
34                 return sizeof( lsampl_t );
35         else
36                 return sizeof( sampl_t );
37 }
38
39 static inline unsigned int bytes_per_scan( comedi_subdevice *subd )
40 {
41         return subd->async->cmd.chanlist_len * bytes_per_sample( subd );
42 }
43
44 static void increment_scan_progress( comedi_subdevice *subd, unsigned int num_bytes )
45 {
46         comedi_async *async = subd->async;
47         unsigned int scan_length = bytes_per_scan( subd );
48
49         async->scan_progress += num_bytes;
50         if( async->scan_progress >= scan_length )
51         {
52                 async->scan_progress %= scan_length;
53                 async->events |= COMEDI_CB_EOS;
54         }
55 }
56
57 /* Writes an array of data points to comedi's buffer */
58 unsigned int cfc_write_array_to_buffer( comedi_subdevice *subd, void *data,
59         unsigned int num_bytes )
60 {
61         comedi_async *async = subd->async;
62         unsigned int retval;
63
64         retval = comedi_buf_write_alloc( async, num_bytes );
65         if( retval != num_bytes )
66         {
67                 async->events |= COMEDI_CB_ERROR;
68                 return 0;
69         }
70
71         comedi_buf_memcpy_to( async, 0, data, num_bytes);
72
73         comedi_buf_write_free( async, num_bytes );
74
75         increment_scan_progress( subd, num_bytes );
76
77         if( num_bytes ) async->events |= COMEDI_CB_BLOCK;
78
79         return num_bytes;
80 }
81
82 unsigned int cfc_read_array_from_buffer( comedi_subdevice *subd, void *data,
83         unsigned int num_bytes )
84 {
85         comedi_async *async = subd->async;
86         unsigned int bytes_available;
87
88         bytes_available = comedi_buf_read_n_available( async );
89         if( bytes_available < num_bytes )
90         {
91                 num_bytes = bytes_available;
92         }
93
94         comedi_buf_memcpy_from( async, 0, data, num_bytes);
95
96         comedi_buf_read_free( async, num_bytes );
97
98         increment_scan_progress( subd, num_bytes );
99
100         if( num_bytes ) async->events |= COMEDI_CB_BLOCK;
101
102         return num_bytes;
103 }
104
105 MODULE_AUTHOR("Frank Mori Hess <fmhess@users.sourceforge.net>");
106 MODULE_DESCRIPTION("Shared functoins for Comedi low-level drivers");
107 MODULE_LICENSE("GPL");
108
109 static int __init comedi_fc_init_module(void)
110 {
111         return 0;
112 }
113 static void __exit comedi_fc_cleanup_module(void)
114 {
115 }
116 module_init(comedi_fc_init_module);
117 module_exit(comedi_fc_cleanup_module);
118
119 EXPORT_SYMBOL( cfc_write_array_to_buffer );
120 EXPORT_SYMBOL( cfc_read_array_from_buffer );