RTXI 1.3
comedi/comedi/range.c
Go to the documentation of this file.
00001 /*
00002     module/range.c
00003     comedi routines for voltage ranges
00004 
00005     COMEDI - Linux Control and Measurement Device Interface
00006     Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
00007 
00008     This program is free software; you can redistribute it and/or modify
00009     it under the terms of the GNU General Public License as published by
00010     the Free Software Foundation; either version 2 of the License, or
00011     (at your option) any later version.
00012 
00013     This program is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016     GNU General Public License for more details.
00017 
00018     You should have received a copy of the GNU General Public License
00019     along with this program; if not, write to the Free Software
00020     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00021 
00022 */
00023 
00024 #include <linux/comedidev.h>
00025 #include <asm/uaccess.h>
00026 
00027 const comedi_lrange range_bipolar10 = { 1, {BIP_RANGE(10)} };
00028 const comedi_lrange range_bipolar5 = { 1, {BIP_RANGE(5)} };
00029 const comedi_lrange range_bipolar2_5 = { 1, {BIP_RANGE(2.5)} };
00030 const comedi_lrange range_unipolar10 = { 1, {UNI_RANGE(10)} };
00031 const comedi_lrange range_unipolar5 = { 1, {UNI_RANGE(5)} };
00032 const comedi_lrange range_unknown = { 1, {{0, 1000000, UNIT_none}} };
00033 
00034 /*
00035         COMEDI_RANGEINFO
00036         range information ioctl
00037 
00038         arg:
00039                 pointer to rangeinfo structure
00040 
00041         reads:
00042                 range info structure
00043 
00044         writes:
00045                 n comedi_krange structures to rangeinfo->range_ptr
00046 */
00047 int do_rangeinfo_ioctl(comedi_device * dev, comedi_rangeinfo * arg)
00048 {
00049         comedi_rangeinfo it;
00050         int subd, chan;
00051         const comedi_lrange *lr;
00052         comedi_subdevice *s;
00053 
00054         if (copy_from_user(&it, arg, sizeof(comedi_rangeinfo)))
00055                 return -EFAULT;
00056         subd = (it.range_type >> 24) & 0xf;
00057         chan = (it.range_type >> 16) & 0xff;
00058 
00059         if (!dev->attached)
00060                 return -EINVAL;
00061         if (subd >= dev->n_subdevices)
00062                 return -EINVAL;
00063         s = dev->subdevices + subd;
00064         if (s->range_table) {
00065                 lr = s->range_table;
00066         } else if (s->range_table_list) {
00067                 if (chan >= s->n_chan)
00068                         return -EINVAL;
00069                 lr = s->range_table_list[chan];
00070         } else {
00071                 return -EINVAL;
00072         }
00073 
00074         if (RANGE_LENGTH(it.range_type) != lr->length) {
00075                 DPRINTK("wrong length %d should be %d (0x%08x)\n",
00076                         RANGE_LENGTH(it.range_type), lr->length, it.range_type);
00077                 return -EINVAL;
00078         }
00079 
00080         if (copy_to_user(it.range_ptr, lr->range,
00081                         sizeof(comedi_krange) * lr->length))
00082                 return -EFAULT;
00083 
00084         return 0;
00085 }
00086 
00087 static int aref_invalid(comedi_subdevice * s, unsigned int chanspec)
00088 {
00089         unsigned int aref;
00090 
00091         // disable reporting invalid arefs... maybe someday
00092         return 0;
00093 
00094         aref = CR_AREF(chanspec);
00095         switch (aref) {
00096         case AREF_DIFF:
00097                 if (s->subdev_flags & SDF_DIFF)
00098                         return 0;
00099                 break;
00100         case AREF_COMMON:
00101                 if (s->subdev_flags & SDF_COMMON)
00102                         return 0;
00103                 break;
00104         case AREF_GROUND:
00105                 if (s->subdev_flags & SDF_GROUND)
00106                         return 0;
00107                 break;
00108         case AREF_OTHER:
00109                 if (s->subdev_flags & SDF_OTHER)
00110                         return 0;
00111                 break;
00112         default:
00113                 break;
00114         }
00115         DPRINTK("subdevice does not support aref %i", aref);
00116         return 1;
00117 }
00118 
00119 /*
00120    This function checks each element in a channel/gain list to make
00121    make sure it is valid.
00122 */
00123 int check_chanlist(comedi_subdevice * s, int n, unsigned int *chanlist)
00124 {
00125         int i;
00126         int chan;
00127 
00128         if (s->range_table) {
00129                 for (i = 0; i < n; i++)
00130                         if (CR_CHAN(chanlist[i]) >= s->n_chan ||
00131                                 CR_RANGE(chanlist[i]) >= s->range_table->length
00132                                 || aref_invalid(s, chanlist[i])) {
00133                                 rt_printk
00134                                         ("bad chanlist[%d]=0x%08x n_chan=%d range length=%d\n",
00135                                         i, chanlist[i], s->n_chan,
00136                                         s->range_table->length);
00137 #if 0
00138                                 for (i = 0; i < n; i++) {
00139                                         printk("[%d]=0x%08x\n", i, chanlist[i]);
00140                                 }
00141 #endif
00142                                 return -EINVAL;
00143                         }
00144         } else if (s->range_table_list) {
00145                 for (i = 0; i < n; i++) {
00146                         chan = CR_CHAN(chanlist[i]);
00147                         if (chan >= s->n_chan ||
00148                                 CR_RANGE(chanlist[i]) >=
00149                                 s->range_table_list[chan]->length
00150                                 || aref_invalid(s, chanlist[i])) {
00151                                 rt_printk("bad chanlist[%d]=0x%08x\n", i,
00152                                         chanlist[i]);
00153                                 return -EINVAL;
00154                         }
00155                 }
00156         } else {
00157                 rt_printk("comedi: (bug) no range type list!\n");
00158                 return -EINVAL;
00159         }
00160         return 0;
00161 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines