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

Attachment: pgp00000.pgp
Description: PGP signature

Reply via email to