Re: [BlueZ PATCH v8 1/6] shared/ad: Add support of bt_ad_pattern

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

 



Hi Miao,

On Fri, Oct 30, 2020 at 5:56 PM Miao-chen Chou <mcchou@xxxxxxxxxxxx> wrote:
>
> This adds struct bt_ad_pattern and helpers functions to facilitate
> pattern matching.
>
> Reviewed-by: Archie Pusaka <apusaka@xxxxxxxxxxxx>
> Reviewed-by: Sonny Sasaka <sonnysasaka@xxxxxxxxxxxx>
> Reviewed-by: Howard Chung <howardchung@xxxxxxxxxx>
> ---
>
> Changes in v8:
> - Modify signature of ad_replace_data() to avoid memory copy
>
>  src/shared/ad.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++-
>  src/shared/ad.h |  16 +++++
>  2 files changed, 166 insertions(+), 1 deletion(-)
>
> diff --git a/src/shared/ad.c b/src/shared/ad.c
> index a34d7a147..23c8c34f4 100644
> --- a/src/shared/ad.c
> +++ b/src/shared/ad.c
> @@ -31,6 +31,12 @@ struct bt_ad {
>         struct queue *data;
>  };
>
> +struct pattern_match_info {
> +       struct bt_ad *ad;
> +       struct bt_ad_pattern *current_pattern;
> +       struct bt_ad_pattern *matched_pattern;
> +};
> +
>  struct bt_ad *bt_ad_new(void)
>  {
>         struct bt_ad *ad;
> @@ -46,6 +52,65 @@ struct bt_ad *bt_ad_new(void)
>         return bt_ad_ref(ad);
>  }
>
> +static bool ad_replace_data(struct bt_ad *ad, uint8_t type, const void *data,
> +                                                       size_t len);
> +
> +static bool ad_is_type_valid(uint8_t type)
> +{
> +       if (type > BT_AD_3D_INFO_DATA && type != BT_AD_MANUFACTURER_DATA)
> +               return false;
> +       if (type < BT_AD_FLAGS)
> +               return false;
> +
> +       return true;
> +}
> +
> +struct bt_ad *bt_ad_new_with_data(size_t len, const uint8_t *data)
> +{
> +       struct bt_ad *ad;
> +       uint16_t parsed_len = 0;
> +
> +       if (data == NULL || !len)
> +               return NULL;
> +
> +       ad = bt_ad_new();
> +       if (!ad)
> +               return NULL;
> +
> +       while (parsed_len < len - 1) {
> +               uint8_t d_len;
> +               uint8_t d_type;
> +               const uint8_t *d;
> +               uint8_t field_len = data[0];
> +
> +               if (field_len == 0)
> +                       break;
> +
> +               parsed_len += field_len + 1;
> +
> +               if (parsed_len > len)
> +                       break;
> +
> +               d = &data[2];
> +               d_type = data[1];
> +               d_len = field_len - 1;
> +
> +               if (!ad_is_type_valid(d_type))
> +                       goto failed;
> +
> +               if (!ad_replace_data(ad, d_type, d, d_len))
> +                       goto failed;
> +
> +               data += field_len + 1;
> +       }
> +
> +       return ad;
> +
> +failed:
> +       bt_ad_unref(ad);
> +       return NULL;
> +}
> +
>  struct bt_ad *bt_ad_ref(struct bt_ad *ad)
>  {
>         if (!ad)
> @@ -126,7 +191,7 @@ static bool data_type_match(const void *data, const void *user_data)
>         return a->type == type;
>  }
>
> -static bool ad_replace_data(struct bt_ad *ad, uint8_t type, void *data,
> +static bool ad_replace_data(struct bt_ad *ad, uint8_t type, const void *data,
>                                                         size_t len)
>  {
>         struct bt_ad_data *new_data;
> @@ -994,3 +1059,87 @@ void bt_ad_clear_data(struct bt_ad *ad)
>
>         queue_remove_all(ad->data, NULL, NULL, data_destroy);
>  }
> +
> +struct bt_ad_pattern *bt_ad_pattern_new(uint8_t type, size_t offset, size_t len,
> +                                                       const uint8_t *data)
> +{
> +       struct bt_ad_pattern *pattern;
> +
> +       if (!data || !len || offset >= BT_AD_MAX_DATA_LEN ||
> +               len > BT_AD_MAX_DATA_LEN || offset + len > BT_AD_MAX_DATA_LEN) {
> +               return NULL;
> +       }
> +
> +       if (!ad_is_type_valid(type))
> +               return NULL;
> +
> +       pattern = new0(struct bt_ad_pattern, 1);
> +       if (!pattern)
> +               return NULL;
> +
> +       pattern->len = len;
> +       pattern->type = type;
> +       pattern->offset = offset;
> +       memcpy(pattern->data, data, len);
> +
> +       return pattern;
> +}
> +
> +static void pattern_ad_data_match(void *data, void *user_data)
> +{
> +       struct bt_ad_data *ad_data = data;
> +       struct pattern_match_info *info = user_data;
> +       struct bt_ad_pattern *pattern;
> +
> +       if (!ad_data || !info)
> +               return;
> +
> +       if (info->matched_pattern)
> +               return;
> +
> +       pattern = info->current_pattern;
> +
> +       if (!pattern || ad_data->type != pattern->type)
> +               return;
> +
> +       if (ad_data->len < pattern->offset + pattern->len)
> +               return;
> +
> +       if (!memcmp(ad_data->data + pattern->offset, pattern->data,
> +                                                               pattern->len)) {
> +               info->matched_pattern = pattern;
> +       }
> +}
> +
> +static void pattern_match(void *data, void *user_data)
> +{
> +       struct bt_ad_pattern *pattern = data;
> +       struct pattern_match_info *info = user_data;
> +
> +       if (!pattern || !info)
> +               return;
> +
> +       if (info->matched_pattern)
> +               return;
> +
> +       info->current_pattern = pattern;
> +
> +       bt_ad_foreach_data(info->ad, pattern_ad_data_match, info);
> +}
> +
> +struct bt_ad_pattern *bt_ad_pattern_match(struct bt_ad *ad,
> +                                                       struct queue *patterns)
> +{
> +       struct pattern_match_info info;
> +
> +       if (!ad || queue_isempty(patterns))
> +               return NULL;
> +
> +       info.ad = ad;
> +       info.matched_pattern = NULL;
> +       info.current_pattern = NULL;
> +
> +       queue_foreach(patterns, pattern_match, &info);
> +
> +       return info.matched_pattern;
> +}
> diff --git a/src/shared/ad.h b/src/shared/ad.h
> index 83eacab66..13adcb406 100644
> --- a/src/shared/ad.h
> +++ b/src/shared/ad.h
> @@ -68,6 +68,7 @@
>  typedef void (*bt_ad_func_t)(void *data, void *user_data);
>
>  struct bt_ad;
> +struct queue;
>
>  struct bt_ad_manufacturer_data {
>         uint16_t manufacturer_id;
> @@ -87,8 +88,17 @@ struct bt_ad_data {
>         size_t len;
>  };
>
> +struct bt_ad_pattern {
> +       uint8_t type;
> +       uint8_t offset;
> +       uint8_t len;
> +       uint8_t data[BT_AD_MAX_DATA_LEN];
> +};
> +
>  struct bt_ad *bt_ad_new(void);
>
> +struct bt_ad *bt_ad_new_with_data(size_t len, const uint8_t *data);
> +
>  struct bt_ad *bt_ad_ref(struct bt_ad *ad);
>
>  void bt_ad_unref(struct bt_ad *ad);
> @@ -156,3 +166,9 @@ void bt_ad_foreach_data(struct bt_ad *ad, bt_ad_func_t func, void *user_data);
>  bool bt_ad_remove_data(struct bt_ad *ad, uint8_t type);
>
>  void bt_ad_clear_data(struct bt_ad *ad);
> +
> +struct bt_ad_pattern *bt_ad_pattern_new(uint8_t type, size_t offset,
> +                                       size_t len, const uint8_t *data);
> +
> +struct bt_ad_pattern *bt_ad_pattern_match(struct bt_ad *ad,
> +                                                       struct queue *patterns);
> --
> 2.26.2

Applied, thanks.

-- 
Luiz Augusto von Dentz



[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