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);