from ds
[comedilib.git] / lib / comedi.c
1 /*
2     lib/comedi.c
3     generic functions
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 <sys/ioctl.h>
32 #include <errno.h>
33 #include <comedi.h>
34 #include <string.h>
35
36 #include <libinternal.h>
37
38 INTERNAL int __comedi_init=0;
39
40 INTERNAL void initialize(void)
41 {
42         char *s;
43         
44         __comedi_init=1;
45
46         if( (s=getenv("COMEDILIB_LOGLEVEL")) ){
47                 __comedi_loglevel=strtol(s,NULL,0);
48                 DEBUG(3,"setting loglevel to %d\n",__comedi_loglevel);
49         }
50 }
51   
52 comedi_t *comedi_open(const char *fn)
53 {
54         comedi_t *it;
55
56         if(!__comedi_init)
57                 initialize();
58
59         if(!(it=malloc(sizeof(comedi_t))))
60                 goto cleanup;
61         memset(it,0,sizeof(comedi_t));
62
63         if((it->fd=open(fn,O_RDWR))<0){
64                 libc_error();
65                 goto cleanup;
66         }
67
68         if(ioctl_devinfo(it->fd,&it->devinfo)<0)
69                 goto cleanup;
70
71         it->n_subdevices=it->devinfo.n_subdevs;
72
73         get_subdevices(it);
74
75         it->magic=COMEDILIB_MAGIC;
76
77         return it;
78 cleanup:
79         if(it)
80                 free(it);
81
82         return NULL;
83 }
84
85 #if 0
86 /* this is an example of how we do versioned symbols */
87 __asm__(".symver comedi_open_0,comedi_open@");
88 #endif
89
90 int comedi_close(comedi_t *it)
91 {
92         subdevice *s;
93         int i;
94
95         it->magic=0;
96
97         for(i=0;i<it->n_subdevices;i++){
98                 s=it->subdevices+i;
99                 if(s->type==COMEDI_SUBD_UNUSED)
100                         continue;
101
102                 if(s->subd_flags&SDF_FLAGS){
103                         free(s->flags_list);
104                 }
105                 if(s->subd_flags&SDF_MAXDATA){
106                         free(s->maxdata_list);
107                 }
108                 if(s->subd_flags&SDF_RANGETYPE){
109                         free(s->range_type_list);
110                         free(s->rangeinfo_list);
111                 }else{
112                         free(s->rangeinfo);
113                 }
114                 if(s->cmd_mask)free(s->cmd_mask);
115                 if(s->cmd_timed)free(s->cmd_timed);
116         }
117         if(it->subdevices){
118                 free(it->subdevices);
119         }
120         close(it->fd);
121         free(it);
122         return 0;
123 }
124
125 int comedi_cancel(comedi_t *it,unsigned int subdevice)
126 {
127         return ioctl(it->fd,COMEDI_CANCEL,subdevice);
128 }
129
130 int comedi_poll(comedi_t *it,unsigned int subdevice)
131 {
132         return ioctl(it->fd,COMEDI_POLL,subdevice);
133 }
134
135 int comedi_fileno(comedi_t *it)
136 {
137         if(!it)
138                 return -1;
139
140         return it->fd;
141 }
142
143 int comedi_trigger(comedi_t *it,comedi_trig *t)
144 {
145         if(!it || !t)
146                 return -1;
147
148         return ioctl_trigger(it->fd,t);
149 }
150
151 int comedi_command(comedi_t *it,comedi_cmd *t)
152 {
153         int ret;
154         ret = ioctl(it->fd,COMEDI_CMD,t);
155         __comedi_errno = errno;
156         switch(__comedi_errno){
157         case EIO:
158                 __comedi_errno = ECMDNOTSUPP;
159                 break;
160         }
161         return ret;
162 }
163
164 int comedi_command_test(comedi_t *it,comedi_cmd *t)
165 {
166         int ret;
167         ret = ioctl(it->fd,COMEDI_CMDTEST,t);
168         __comedi_errno = errno;
169         switch(__comedi_errno){
170         case EIO:
171                 __comedi_errno = ECMDNOTSUPP;
172                 break;
173         }
174         return ret;
175 }
176
177 int comedi_do_insnlist(comedi_t *it,comedi_insnlist *il)
178 {
179         int ret;
180         ret = ioctl(it->fd,COMEDI_INSNLIST,il);
181         __comedi_errno = errno;
182         return ret;
183 }
184
185 int comedi_do_insn(comedi_t *it,comedi_insn *insn)
186 {
187         if(it->has_insn_ioctl){
188                 return ioctl(it->fd,COMEDI_INSN,insn);
189         }else{
190                 comedi_insnlist il;
191                 int ret;
192
193                 il.n_insns = 1;
194                 il.insns = insn;
195
196                 ret = ioctl(it->fd,COMEDI_INSNLIST,&il);
197
198                 if(ret<0)return ret;
199                 return insn->n;
200         }
201 }
202
203 int comedi_lock(comedi_t *it,unsigned int subdevice)
204 {
205         return ioctl(it->fd,COMEDI_LOCK,subdevice);
206 }
207
208 int comedi_unlock(comedi_t *it,unsigned int subdevice)
209 {
210         return ioctl(it->fd,COMEDI_UNLOCK,subdevice);
211 }
212