fix ruby prefix to work for distcheck
[comedilib.git] / lib / dio.c
1 /*
2     lib/dio.c
3     digital I/O routines
4
5     COMEDILIB - Linux Control and Measurement Device Interface Library
6     Copyright (C) 1997-2001 David A. Schleef <ds@schleef.org>
7
8     This library is free software; you can redistribute it and/or
9     modify it under the terms of the GNU Lesser General Public
10     License as published by the Free Software Foundation, version 2.1
11     of the License.
12
13     This library is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16     Lesser General Public License for more details.
17
18     You should have received a copy of the GNU Lesser General Public
19     License along with this library; if not, write to the Free Software
20     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
21     USA.
22 */
23
24 #include <stdio.h>
25 #include <math.h>
26 #include <stdlib.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <errno.h>
32 #include <string.h>
33
34 #include "libinternal.h"
35
36
37 EXPORT_ALIAS_DEFAULT(_comedi_dio_config,comedi_dio_config,0.7.18);
38 int _comedi_dio_config(comedi_t *it,unsigned int subdev,unsigned int chan,unsigned int io)
39 {
40         subdevice *s;
41
42         if(!valid_chan(it,subdev,chan))
43                 return -1;
44         
45         s=it->subdevices+subdev;
46         if(s->type!=COMEDI_SUBD_DIO)
47                 return -1;
48
49         if(io!=COMEDI_INPUT && io!=COMEDI_OUTPUT)
50                 return -1;
51
52         if(it->has_insnlist_ioctl){
53                 comedi_insn insn;
54                 lsampl_t data;
55                 
56                 memset(&insn,0,sizeof(insn));
57                 insn.insn = INSN_CONFIG;
58                 insn.n = 1;
59                 insn.data = &data;
60                 insn.subdev = subdev;
61                 insn.chanspec = CR_PACK(chan,0,0);
62                 data=io;
63
64                 return comedi_do_insn(it,&insn);
65         }else
66         {
67                 comedi_trig trig;
68                 sampl_t data=io;
69
70                 memset(&trig,0,sizeof(trig));
71                 trig.flags=TRIG_CONFIG|TRIG_WRITE;
72                 trig.n_chan=1;
73                 trig.n=1;
74                 trig.subdev=subdev;
75                 trig.chanlist=&chan;
76                 trig.data=&data;
77
78                 return comedi_trigger(it,&trig);
79         }
80 }
81
82 EXPORT_ALIAS_DEFAULT(_comedi_dio_read,comedi_dio_read,0.7.18);
83 int _comedi_dio_read(comedi_t *it,unsigned int subdev,unsigned int chan,
84         unsigned int *val)
85 {
86         subdevice *s;
87         int ret;
88
89         if(!valid_chan(it,subdev,chan))
90                 return -1;
91
92         s = it->subdevices+subdev;
93         if(s->type!=COMEDI_SUBD_DIO &&
94            s->type!=COMEDI_SUBD_DO &&
95            s->type!=COMEDI_SUBD_DI)
96                 return -1;
97
98         if(it->has_insnlist_ioctl){
99                 comedi_insn insn;
100                 lsampl_t data;
101                 
102                 memset(&insn,0,sizeof(insn));
103                 insn.insn = INSN_READ;
104                 insn.n = 1;
105                 insn.data = &data;
106                 insn.subdev = subdev;
107                 insn.chanspec = CR_PACK(chan,0,0);
108
109                 ret = comedi_do_insn(it,&insn);
110
111                 *val = data;
112
113                 return ret;
114         }else{
115                 comedi_trig trig;
116                 sampl_t data;
117
118                 memset(&trig,0,sizeof(trig));
119                 trig.n_chan=1;
120                 trig.n=1;
121                 trig.subdev=subdev;
122                 trig.chanlist=&chan;
123                 trig.data=&data;
124
125                 ret=comedi_trigger(it,&trig);
126
127                 if(ret>=0 && val)*val=data;
128
129                 return ret;
130         }
131 }
132
133 EXPORT_ALIAS_DEFAULT(_comedi_dio_write,comedi_dio_write,0.7.18);
134 int _comedi_dio_write(comedi_t *it,unsigned int subdev,unsigned int chan,
135         unsigned int val)
136 {
137         subdevice *s;
138
139         if(!valid_chan(it,subdev,chan))
140                 return -1;
141         
142         s = it->subdevices+subdev;
143         if(s->type!=COMEDI_SUBD_DIO &&
144            s->type!=COMEDI_SUBD_DO)
145                 return -1;
146
147         if(it->has_insnlist_ioctl){
148                 comedi_insn insn;
149                 lsampl_t data;
150                 
151                 memset(&insn,0,sizeof(insn));
152                 insn.insn = INSN_WRITE;
153                 insn.n = 1;
154                 insn.data = &data;
155                 insn.subdev = subdev;
156                 insn.chanspec = CR_PACK(chan,0,0);
157
158                 data = val;
159
160                 return comedi_do_insn(it,&insn);
161         }else{
162                 comedi_trig trig;
163                 sampl_t data;
164
165                 data=val;
166
167                 memset(&trig,0,sizeof(trig));
168                 trig.n_chan=1;
169                 trig.n=1;
170                 trig.flags=TRIG_WRITE;
171                 trig.subdev=subdev;
172                 trig.chanlist=&chan;
173                 trig.data=&data;
174
175                 return comedi_trigger(it,&trig);
176         }
177 }
178
179 EXPORT_ALIAS_DEFAULT(_comedi_dio_bitfield,comedi_dio_bitfield,0.7.18);
180 int _comedi_dio_bitfield(comedi_t *it,unsigned int subdev,unsigned int mask,unsigned int *bits)
181 {
182         int ret;
183         unsigned int m,bit;
184         subdevice *s;
185
186         if(!valid_subd(it,subdev))
187                 return -1;
188
189         s=it->subdevices+subdev;
190
191         if(s->type!=COMEDI_SUBD_DIO && s->type!=COMEDI_SUBD_DO &&
192            s->type!=COMEDI_SUBD_DI)
193                 return -1;
194
195         if(s->has_insn_bits){
196                 comedi_insn insn;
197                 lsampl_t data[2];
198                 
199                 memset(&insn,0,sizeof(insn));
200
201                 insn.insn = INSN_BITS;
202                 insn.n = 2;
203                 insn.data = data;
204                 insn.subdev = subdev;
205
206                 data[0]=mask;
207                 data[1]=*bits;
208
209                 ret = comedi_do_insn(it,&insn);
210
211                 if(ret<0)return ret;
212
213                 *bits = data[1];
214
215                 return 0;
216         }else{
217                 unsigned int i,n_chan;
218
219                 n_chan=comedi_get_n_channels(it,subdev);
220                 if(n_chan>32)n_chan=32;
221                 for(i=0,m=1;i<n_chan;i++,m<<=1){
222                         if(mask&m){
223                                 bit=(*bits&m)?1:0;
224                                 ret=comedi_dio_write(it,subdev,i,bit);
225                         }else{
226                                 ret=comedi_dio_read(it,subdev,i,&bit);
227                                 if(bit) *bits|=m;
228                                 else (*bits)&=~m;
229                         }
230                         if(ret<0)return ret;
231                 }
232                 return (int)n_chan;
233         }
234 }
235