Re: [PATCH 1/2] hog: Fix checking for Report ID item

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Andrzej,

On Tue, Apr 29, 2014 at 12:29 PM, Andrzej Kaczmarek
<andrzej.kaczmarek@xxxxxxxxx> wrote:
> Report ID item is detected by just looking for possible item prefixes
> anywhere in report map. This could lead to false-positive detection if
> value we look for is inside item data.
>
> This patch adds simple parser which can split report map into proper
> items and check for Report ID item in reliable way.

Well it looks like the format of each descriptor can be different so I
would add this to the patch description and probably quote from spec
what is those formats.

> ---
>  profiles/input/hog.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 55 insertions(+), 5 deletions(-)
>
> diff --git a/profiles/input/hog.c b/profiles/input/hog.c
> index a11e04e..ab88414 100644
> --- a/profiles/input/hog.c
> +++ b/profiles/input/hog.c
> @@ -345,6 +345,39 @@ static void external_report_reference_cb(guint8 status, const guint8 *pdu,
>                                         external_service_char_cb, hogdev);
>  }
>
> +static bool parse_descriptor_item(uint8_t *buf, ssize_t blen, ssize_t *len,
> +                                                               bool *is_long)
> +{
> +       if (!blen)
> +               return false;
> +
> +       if (buf[0] == 0xFE) {
> +               if (blen < 3)
> +                       return false;
> +               /* long item:
> +                * byte 0 -> 0xFE
> +                * byte 1 -> data size
> +                * byte 2 -> tag
> +                * + data
> +                */
> +               *len = buf[1] + 3;
> +               *is_long = true;
> +       } else {
> +               uint8_t b_size;
> +               /* short item:
> +                * byte 0[1..0] -> data size (=0, 1, 2, 4)
> +                * byte 0[3..2] -> type
> +                * byte 0[7..4] -> tag
> +                * + data
> +                */
> +               b_size = buf[0] & 0x03;
> +               *len = (b_size ? 1 << (b_size - 1) : 0) + 1;
> +               *is_long = false;
> +       }

Perhaps split this into 2 functions one to parse sort descriptors and
one for long descriptors, also you can probably drop the item suffix
e.g.: parse_short_descriptor, parse_long_descriptor.

> +       return *len <= blen;
> +}
> +
>  static void report_map_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
>                                                         gpointer user_data)
>  {
> @@ -355,6 +388,7 @@ static void report_map_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
>         uint16_t vendor_src, vendor, product, version;
>         ssize_t vlen;
>         int i;
> +       int next_item = 0;
>
>         if (status != 0) {
>                 error("Report Map read failed: %s", att_ecode2str(status));
> @@ -369,11 +403,27 @@ static void report_map_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
>
>         DBG("Report MAP:");
>         for (i = 0; i < vlen; i++) {
> -               switch (value[i]) {
> -               case 0x85:
> -               case 0x86:
> -               case 0x87:
> -                       hogdev->has_report_id = TRUE;
> +               ssize_t item_len = 0;
> +               bool is_long_item = false;
> +
> +               if (i == next_item) {
> +                       if (parse_descriptor_item(&value[i], vlen - i,
> +                                                       &item_len,
> +                                                       &is_long_item)) {
> +                               /* Report ID is short item with prefix
> +                                * 100001xx (binary)
> +                                */
> +                               if (!is_long_item && (value[i] & 0xfc) == 0x84)

Hmm, so long descriptors are ignored? Is that really what we want?

> +                                       hogdev->has_report_id = TRUE;
> +
> +                               next_item += item_len;
> +                       } else {
> +                               error("Report Map parsing failed at %d", i);
> +
> +                               /* We do not increase next_item here so we won't
> +                                * parse subsequent data - this is what we want.
> +                                */
> +                       }
>                 }
>
>                 if (i % 2 == 0) {
> --
> 1.9.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Luiz Augusto von Dentz
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux