Bump.
This patch fixes "runtime" error in libusbhid when parsing usage strings
with usage defined in default usbhid table as a format string.




On Tue, May 29, 2018, 10:29 PM David Bern <david.ml.b...@gmail.com> wrote:

> Sorry for the spamming.
> After some research and finding that my fix for issue nr: 2 (
> hid_usage_in_page() )
> will break the functionality inside /usr.bin/usbhidaction/usbhidaction.c
> https://goo.gl/1cWFtR (link to usbhidaction.c)
>
> I now change my patch to only include a fix for issue nr: 1
> More details is described in the previous mail
>
> Index: usage.c
> ===================================================================
> RCS file: /cvs/src/lib/libusbhid/usage.c,v
> retrieving revision 1.16
> diff -u -p -r1.16 usage.c
> --- usage.c     8 Oct 2014 04:49:36 -0000       1.16
> +++ usage.c     29 May 2018 19:45:25 -0000
> @@ -265,8 +265,9 @@ int
>  hid_parse_usage_in_page(const char *name)
>  {
>         const char *sep;
> +       const char *usage_sep;
>         unsigned int l;
> -       int k, j;
> +       int k, j, us, parsed_usage;
>
>         sep = strchr(name, ':');
>         if (sep == NULL)
> @@ -278,9 +279,19 @@ hid_parse_usage_in_page(const char *name
>         return -1;
>   found:
>         sep++;
> -       for (j = 0; j < pages[k].pagesize; j++)
> +       for (j = 0; j < pages[k].pagesize; j++) {
> +               us = pages[k].page_contents[j].usage;
> +               if (us == -1) {
> +                       usage_sep = strchr(sep, '_');
> +                       if (usage_sep == NULL)
> +                               return -1;
> +                       if (sscanf(usage_sep, "_%d", &parsed_usage))
> +                               return (pages[k].usage << 16) |
> +                                   parsed_usage;
> +               }
>                 if (strcmp(pages[k].page_contents[j].name, sep) == 0)
>                         return (pages[k].usage << 16) |
>                             pages[k].page_contents[j].usage;
> +       }
>         return -1;
>  }
>
>
> comments? ok?
>
> 2018-05-28 13:01 GMT+02:00 David Bern <david.ml.b...@gmail.com>:
>
>> I was suggested off list to give an explanation on what the patch does.
>>
>> So please, tell me if I need to clarify more, or make further changes to
>> the code.
>>
>> The patch tries to fix two things.
>> 1. Changes in hid_parse_usage_in_page() fixes problems in parsing usages
>> defined as:  *       Button %d
>>
>> hid_parse_usage_in_page():
>> Previously - With input "Button:Button_1" returns -1
>> Now - With input "Button:Button_1" returns 589825
>>
>> In the scenario of parsing Button:Button_1 we will not find a usage name
>> matching that string. For example Button:Button_1 is defined as
>> Button %d in the table.
>>
>> We are still able to calculate the proper usage number in the same way we
>> are
>> able to calculate the proper usage name in hid_usage_in_page().
>>
>> The first step is to identify if usage name is shortened. If it is,
>> usage will hold a value of -1. Then I try to locate a separator char in
>> the name as "_".
>> If a separator char is found I use it to read the value as "_%d" to get
>> the
>> corresponding usage number
>>
>> >+               us = pages[k].page_contents[j].usage;
>> >+               if (us == -1) {
>> >+                       usage_sep = strchr(sep, '_');
>> >+                       if (usage_sep == NULL)
>> >+                               return -1;
>> >+                       if (sscanf(usage_sep, "_%d", &parsed_usage))
>> >+                               return (pages[k].usage << 16) |
>> >+                                               parsed_usage;
>>
>>
>> 2. The text-string that is returned by hid_usage_in_page() misses page
>> information.
>> So the changes made in hid_usage_in_page() is to make it the inverse of
>> hid_parse_usage_in_page()
>>
>> In details what the code previously did and now does.
>>
>> hid_usage_in_page():
>> Previously - With input 589825 returns Button_1
>> Now - With input 589825 returns Button:Button_1
>>
>>
>> The change just adds a pages[k].name to the string, a format that
>> hid_parse_usage_in_page() expects it to have.
>> I make formatting in two steps when us == -1 which it is when usage is
>> shortened
>> as for example: *       Button %d.
>>
>> >+                       snprintf(fmt, sizeof fmt,
>> >+                           "%%s:%s", pages[k].page_contents[j].name);
>> >+                       snprintf(b, sizeof b, fmt, pages[k].name, i);
>>
>> The first step is to create a format string that will result in something
>> like
>>  "%s:Button_%d".
>> The last step I use the fmt-string to create a complete string that will
>> result in
>> "Button:Button_1"
>>
>>
>>
>>
>> 2018-05-24 18:44 GMT+02:00 David Bern <david.ml.b...@gmail.com>:
>>
>>> While I was waiting for comments and feedback I came up with some
>>> improvements.
>>> The "logic" is still the same, but the execution is hopefully more sane.
>>>
>>> Index: usage.c
>>> ===================================================================
>>> RCS file: /cvs/src/lib/libusbhid/usage.c,v
>>> retrieving revision 1.16
>>> diff -u -p -r1.16 usage.c
>>> --- usage.c     8 Oct 2014 04:49:36 -0000       1.16
>>> +++ usage.c     24 May 2018 16:37:54 -0000
>>> @@ -224,6 +224,7 @@ hid_usage_in_page(unsigned int u)
>>>  {
>>>         int i = HID_USAGE(u), j, k, us;
>>>         int page = HID_PAGE(u);
>>> +       char fmt[100];
>>>         static char b[100];
>>>
>>>         for (k = 0; k < npages; k++)
>>> @@ -234,12 +235,16 @@ hid_usage_in_page(unsigned int u)
>>>         for (j = 0; j < pages[k].pagesize; j++) {
>>>                 us = pages[k].page_contents[j].usage;
>>>                 if (us == -1) {
>>> -                       snprintf(b, sizeof b,
>>> -                           pages[k].page_contents[j].name, i);
>>> +                       snprintf(fmt, sizeof fmt,
>>> +                           "%%s:%s", pages[k].page_contents[j].name);
>>> +                       snprintf(b, sizeof b, fmt, pages[k].name, i);
>>> +                       return b;
>>> +               }
>>> +               if (us == i) {
>>> +                       snprintf(b, sizeof b, "%s:%s", pages[k].name,
>>> +                           pages[k].page_contents[j].name);
>>>                         return b;
>>>                 }
>>> -               if (us == i)
>>> -                       return pages[k].page_contents[j].name;
>>>         }
>>>   bad:
>>>         snprintf(b, sizeof b, "0x%04x", i);
>>> @@ -265,8 +270,9 @@ int
>>>  hid_parse_usage_in_page(const char *name)
>>>  {
>>>         const char *sep;
>>> +       const char *usage_sep;
>>>         unsigned int l;
>>> -       int k, j;
>>> +       int k, j, us, parsed_usage;
>>>
>>>         sep = strchr(name, ':');
>>>         if (sep == NULL)
>>> @@ -278,9 +284,19 @@ hid_parse_usage_in_page(const char *name
>>>         return -1;
>>>   found:
>>>         sep++;
>>> -       for (j = 0; j < pages[k].pagesize; j++)
>>> +       for (j = 0; j < pages[k].pagesize; j++) {
>>> +               us = pages[k].page_contents[j].usage;
>>> +               if (us == -1) {
>>> +                       usage_sep = strchr(sep, '_');
>>> +                       if (usage_sep == NULL)
>>> +                               return -1;
>>> +                       if (sscanf(usage_sep, "_%d", &parsed_usage))
>>> +                               return (pages[k].usage << 16) |
>>> +                                               parsed_usage;
>>> +               }
>>>                 if (strcmp(pages[k].page_contents[j].name, sep) == 0)
>>>                         return (pages[k].usage << 16) |
>>>                             pages[k].page_contents[j].usage;
>>> +       }
>>>         return -1;
>>>  }
>>>
>>>
>>>
>>> 2018-05-21 23:12 GMT+02:00 David Bern <david.ml.b...@gmail.com>:
>>>
>>>> First diff "solves" point 1 & 2. Second diff is on the parts of the
>>>> manual that does not match the usbhid.h
>>>>
>>>> Index: usage.c
>>>> ===================================================================
>>>> RCS file: /cvs/src/lib/libusbhid/usage.c,v
>>>> retrieving revision 1.16
>>>> diff -u -p -r1.16 usage.c
>>>> --- usage.c     8 Oct 2014 04:49:36 -0000       1.16
>>>> +++ usage.c     21 May 2018 21:06:24 -0000
>>>> @@ -224,6 +224,7 @@ hid_usage_in_page(unsigned int u)
>>>>  {
>>>>         int i = HID_USAGE(u), j, k, us;
>>>>         int page = HID_PAGE(u);
>>>> +       char usage_name[100];
>>>>         static char b[100];
>>>>
>>>>         for (k = 0; k < npages; k++)
>>>> @@ -234,12 +235,18 @@ hid_usage_in_page(unsigned int u)
>>>>         for (j = 0; j < pages[k].pagesize; j++) {
>>>>                 us = pages[k].page_contents[j].usage;
>>>>                 if (us == -1) {
>>>> -                       snprintf(b, sizeof b,
>>>> +                       snprintf(usage_name, sizeof usage_name,
>>>>                             pages[k].page_contents[j].name, i);
>>>> +                       snprintf(b, sizeof b,
>>>> +                           "%s:%s", pages[k].name, usage_name);
>>>> +                       return b;
>>>> +               }
>>>> +               if (us == i) {
>>>> +                       snprintf(b, sizeof b,
>>>> +                           "%s:%s", pages[k].name,
>>>> +                           pages[k].page_contents[j].name);
>>>>                         return b;
>>>>                 }
>>>> -               if (us == i)
>>>> -                       return pages[k].page_contents[j].name;
>>>>         }
>>>>   bad:
>>>>         snprintf(b, sizeof b, "0x%04x", i);
>>>> @@ -265,8 +272,9 @@ int
>>>>  hid_parse_usage_in_page(const char *name)
>>>>  {
>>>>         const char *sep;
>>>> +       const char *usage_sep;
>>>>         unsigned int l;
>>>> -       int k, j;
>>>> +       int k, j, us, parsed_usage;
>>>>
>>>>         sep = strchr(name, ':');
>>>>         if (sep == NULL)
>>>> @@ -277,10 +285,20 @@ hid_parse_usage_in_page(const char *name
>>>>                         goto found;
>>>>         return -1;
>>>>   found:
>>>> +       usage_sep = strchr(sep, '_');
>>>>         sep++;
>>>> -       for (j = 0; j < pages[k].pagesize; j++)
>>>> +       for (j = 0; j < pages[k].pagesize; j++) {
>>>> +               us = pages[k].page_contents[j].usage;
>>>> +               if (us == -1) {
>>>> +                       if (usage_sep == NULL)
>>>> +                               return -1;
>>>> +                       if (sscanf(usage_sep, "_%d", &parsed_usage))
>>>> +                               return (pages[k].usage << 16 |
>>>> +                                               parsed_usage);
>>>> +               }
>>>>                 if (strcmp(pages[k].page_contents[j].name, sep) == 0)
>>>>                         return (pages[k].usage << 16) |
>>>>                             pages[k].page_contents[j].usage;
>>>> +       }
>>>>         return -1;
>>>>  }
>>>>
>>>> Index: usbhid.3
>>>> ===================================================================
>>>> RCS file: /cvs/src/lib/libusbhid/usbhid.3,v
>>>> retrieving revision 1.17
>>>> diff -u -p -r1.17 usbhid.3
>>>> --- usbhid.3    13 May 2014 14:05:02 -0000      1.17
>>>> +++ usbhid.3    21 May 2018 21:02:21 -0000
>>>> @@ -65,22 +65,22 @@
>>>>  .Fn hid_report_size "report_desc_t d" "hid_kind_t k" "int id"
>>>>  .Ft int
>>>>  .Fn hid_locate "report_desc_t d" "u_int usage" "hid_kind_t k"
>>>> "hid_item_t *h" "int id"
>>>> -.Ft char *
>>>> +.Ft const char *
>>>>  .Fn hid_usage_page "int i"
>>>> -.Ft char *
>>>> +.Ft const char *
>>>>  .Fn hid_usage_in_page "u_int u"
>>>>  .Ft int
>>>>  .Fn hid_parse_usage_page "const char *"
>>>> -.Ft char *
>>>> +.Ft int
>>>>  .Fn hid_parse_usage_in_page "const char *"
>>>>  .Ft void
>>>>  .Fn hid_init "char *file"
>>>>  .Ft int
>>>>  .Fn hid_start "char *file"
>>>> -.Ft int
>>>> +.Ft int32_t
>>>>  .Fn hid_get_data "void *data" "hid_item_t *h"
>>>>  .Ft void
>>>> -.Fn hid_set_data "void *data" "hid_item_t *h" "u_int data"
>>>> +.Fn hid_set_data "void *data" "hid_item_t *h" "int32_t data"
>>>>  .Sh DESCRIPTION
>>>>  The
>>>>  .Nm
>>>>
>>>>
>>>>
>>>> 2018-05-21 12:07 GMT+02:00 Martin Pieuchot <m...@openbsd.org>:
>>>>
>>>>> On 18/05/18(Fri) 10:01, David Bern wrote:
>>>>> > Hello!
>>>>> >
>>>>> > Have been using libusbhid and discovered a couple of discrepancies in
>>>>> > the man-page (libusbhid.3) and the source of usage.c
>>>>> >
>>>>> > Some are just factual misses, but I also got (what I think is) 2
>>>>> errors.
>>>>> > I will try to explain them;
>>>>> >
>>>>> > 1. (This is the I think is an error but not sure). The man-page
>>>>> tells me
>>>>> > that hid_usage_in_page and hid_parse_usage_in_page are each
>>>>> > others inverse.
>>>>> > If I haven't misunderstood the practical meaning of inverse in this
>>>>> > case then this should be true:
>>>>> > x == hid_parse_usage_in_page(hid_usage_in_page(x)).
>>>>> >
>>>>> > My observation:
>>>>> > The main reason to why this isnt true, is that hid_usage_in_page()
>>>>> > returns the data of pages[k].page_contents[j].name
>>>>> > while hid_parse_usage_in_page() expects the data to
>>>>> > contain "%s:%s", pages[k].name, pages[k].page_contents[j].name
>>>>> >
>>>>> > The reason I ask instead of just posting working code is this:
>>>>> > Am I misunderstanding the manual? In that case, the solution I want
>>>>> > to send in is a change in that sentence
>>>>> > Or Is the manual correct and the behavior of hid_usage_in_page()
>>>>> wrong,
>>>>> > is this something I can correct without breaking other systems?
>>>>> >
>>>>> >
>>>>> > 2. The second error I found is located in hid_parse_usage_in_page().
>>>>> > It is unable to parse values found in page Button.
>>>>> >
>>>>> > My observation:
>>>>> > usage.c is using a standard table named usb_hid_pages. In that table
>>>>> > we got a page called Buttons.
>>>>> > the usages in that page is shortened to "*  Button %d".
>>>>> > I believe this is the cause of why hid_parse_usage_in_page() is
>>>>> getting
>>>>> > the pagesize "wrong" and therefor unable to parse any button in the
>>>>> > button page. I guess this is the case with other similar cases as
>>>>> well.
>>>>> >
>>>>> > my conclusion is that it would be possible to handle similar cases
>>>>> in a
>>>>> > similar way as it is handled in hid_usage_in_page().
>>>>> >
>>>>> >
>>>>> > As this is my first "issue" I would love to get as much feedback as
>>>>> > possible so I can work on delivering a desirable and usable patch in
>>>>> > my first try.
>>>>>
>>>>> Just send a diff, then we'll look at it 8)
>>>>>
>>>>
>>>>
>>>
>>
>

Reply via email to