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
