summaryrefslogtreecommitdiffstats
path: root/drivers/staging/comedi/comedi_fops.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/comedi/comedi_fops.c')
-rw-r--r--drivers/staging/comedi/comedi_fops.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index 093032ba521a..a4ceb29c358e 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -910,9 +910,28 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn,
case INSN_BITS:
if (insn->n != 2) {
ret = -EINVAL;
- break;
+ } else {
+ /* Most drivers ignore the base channel in
+ * insn->chanspec. Fix this here if
+ * the subdevice has <= 32 channels. */
+ unsigned int shift;
+ unsigned int orig_mask;
+
+ orig_mask = data[0];
+ if (s->n_chan <= 32) {
+ shift = CR_CHAN(insn->chanspec);
+ if (shift > 0) {
+ insn->chanspec = 0;
+ data[0] <<= shift;
+ data[1] <<= shift;
+ }
+ } else
+ shift = 0;
+ ret = s->insn_bits(dev, s, insn, data);
+ data[0] = orig_mask;
+ if (shift > 0)
+ data[1] >>= shift;
}
- ret = s->insn_bits(dev, s, insn, data);
break;
case INSN_CONFIG:
ret = check_insn_config_length(insn, data);