On Thu, May 06, 2004 at 08:22:20PM +1000, Herbert Xu wrote: > On Thu, May 06, 2004 at 08:15:15PM +1000, herbert wrote: > > > > The current code is applying the maxusage limit to GUSAGE/SUSAGE. This > > is incorrect as the number of values is stored in field->report_count, > > not field->maxusage. The USB phone from www.virbiage.com is one device > > where report_count exceeds maxusage. > > > > The following patch corrects the check for 2.6. > > Here is the corresponding patch for 2.4.
This patch seems to break HIDIOCGUCODE for report_type == HID_REPORT_TYPE_INPUT. The following patch (for 2.4) fixes it: --- linux/drivers/usb/hiddev.c.hiddev-fix-gucode 2004-05-07 19:16:41 +0400 +++ linux/drivers/usb/hiddev.c 2004-05-07 19:20:39 +0400 @@ -571,6 +571,7 @@ static int hiddev_ioctl(struct inode *in if (cmd != HIDIOCGUSAGE && cmd != HIDIOCGUSAGES && + cmd != HIDIOCGUCODE && uref->report_type == HID_REPORT_TYPE_INPUT) return -EINVAL; > -- > Debian GNU/Linux 3.0 is out! ( http://www.debian.org/ ) > Email: Herbert Xu ~{PmV>HI~} <[EMAIL PROTECTED]> > Home Page: http://gondor.apana.org.au/~herbert/ > PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt > Index: drivers/usb/hiddev.c > =================================================================== > RCS file: > /home/gondolin/herbert/src/CVS/debian/kernel-source-2.4/drivers/usb/hiddev.c,v > retrieving revision 1.1.1.4 > diff -u -r1.1.1.4 hiddev.c > --- a/drivers/usb/hiddev.c 14 Apr 2004 13:05:32 -0000 1.1.1.4 > +++ b/drivers/usb/hiddev.c 6 May 2004 10:19:59 -0000 > @@ -554,30 +554,11 @@ > > return copy_to_user((void *) arg, &finfo, sizeof(finfo)); > > - case HIDIOCGUCODE: > - if (copy_from_user(uref, (void *) arg, sizeof(*uref))) > - return -EFAULT; > - > - rinfo.report_type = uref->report_type; > - rinfo.report_id = uref->report_id; > - if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) > - return -EINVAL; > - > - if (uref->field_index >= report->maxfield) > - return -EINVAL; > - > - field = report->field[uref->field_index]; > - if (uref->usage_index >= field->maxusage) > - return -EINVAL; > - > - uref->usage_code = field->usage[uref->usage_index].hid; > - > - return copy_to_user((void *) arg, uref, sizeof(*uref)); > - > case HIDIOCGUSAGE: > case HIDIOCSUSAGE: > case HIDIOCGUSAGES: > case HIDIOCSUSAGES: > + case HIDIOCGUCODE: > case HIDIOCGCOLLECTIONINDEX: > if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) { > if (copy_from_user(&uref_multi, (void *) arg, > @@ -593,7 +574,8 @@ > uref->report_type == HID_REPORT_TYPE_INPUT) > return -EINVAL; > > - if (uref->report_id == HID_REPORT_ID_UNKNOWN) { > + if (cmd != HIDIOCGUCODE && > + uref->report_id == HID_REPORT_ID_UNKNOWN) { > field = hiddev_lookup_usage(hid, uref); > if (field == NULL) > return -EINVAL; > @@ -607,26 +589,34 @@ > return -EINVAL; > > field = report->field[uref->field_index]; > - if (uref->usage_index >= field->maxusage) > - return -EINVAL; > - > - if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) { > - if (uref_multi.num_values >= HID_MAX_USAGES || > - uref->usage_index >= field->maxusage || > - (uref->usage_index + uref_multi.num_values) >= > field->maxusage) > + if (cmd == HIDIOCGUCODE || > + cmd == HIDIOCGCOLLECTIONINDEX) { > + if (uref->usage_index >= field->maxusage) > return -EINVAL; > - } > + } else if (uref->usage_index >= field->report_count) > + return -EINVAL; > + else if ((cmd == HIDIOCGUSAGES || > + cmd == HIDIOCSUSAGES) && > + (uref->usage_index + uref_multi.num_values >= > + field->report_count || > + uref->usage_index + uref_multi.num_values < > + uref->usage_index)) > + return -EINVAL; > } > > switch (cmd) { > case HIDIOCGUSAGE: > uref->value = field->value[uref->usage_index]; > - return copy_to_user((void *) arg, uref, sizeof(*uref)); > + break; > > case HIDIOCSUSAGE: > field->value[uref->usage_index] = uref->value; > return 0; > > + case HIDIOCGUCODE: > + uref->usage_code = field->usage[uref->usage_index].hid; > + break; > + > case HIDIOCGCOLLECTIONINDEX: > return field->usage[uref->usage_index].collection_index; > case HIDIOCGUSAGES: > @@ -643,7 +633,10 @@ > uref_multi.values[i]; > return 0; > } > - break; > + > + if (copy_to_user((void *) arg, uref, sizeof(*uref))) > + return -EFAULT; > + return 0; > > case HIDIOCGCOLLECTIONINFO: > if (copy_from_user(&cinfo, (void *) arg, sizeof(cinfo)))
pgp00000.pgp
Description: PGP signature