diff mbox series

[v10,10/10] Bluetooth: Add offload feature under experimental flag

Message ID 20210630080807.12600-10-kiran.k@intel.com (mailing list archive)
State Superseded
Headers show
Series [v10,01/10] Bluetooth: Enumerate local supported codec and cache details | expand

Commit Message

K, Kiran June 30, 2021, 8:08 a.m. UTC
Allow user level process to enable / disable codec offload
feature through mgmt interface. By default offload codec feature
is disabled.

Signed-off-by: Kiran K <kiran.k@intel.com>
Reviewed-by: Chethan T N <chethan.tumkur.narayan@intel.com>
Reviewed-by: Srivatsa Ravishankar <ravishankar.srivatsa@intel.com>
---
* changes in v10:
  - new patch added to place offload codec feature under experimental flag

 include/net/bluetooth/hci.h |   4 ++
 net/bluetooth/mgmt.c        | 106 +++++++++++++++++++++++++++++++++++-
 net/bluetooth/sco.c         |  10 ++++
 3 files changed, 119 insertions(+), 1 deletion(-)

Comments

Luiz Augusto von Dentz June 30, 2021, 7:56 p.m. UTC | #1
Hi Kiran,

On Wed, Jun 30, 2021 at 1:08 AM Kiran K <kiran.k@intel.com> wrote:
>
> Allow user level process to enable / disable codec offload
> feature through mgmt interface. By default offload codec feature
> is disabled.
>
> Signed-off-by: Kiran K <kiran.k@intel.com>
> Reviewed-by: Chethan T N <chethan.tumkur.narayan@intel.com>
> Reviewed-by: Srivatsa Ravishankar <ravishankar.srivatsa@intel.com>
> ---
> * changes in v10:
>   - new patch added to place offload codec feature under experimental flag
>
>  include/net/bluetooth/hci.h |   4 ++
>  net/bluetooth/mgmt.c        | 106 +++++++++++++++++++++++++++++++++++-
>  net/bluetooth/sco.c         |  10 ++++
>  3 files changed, 119 insertions(+), 1 deletion(-)
>
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index e20318854900..5ca98d9f64dd 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -331,6 +331,10 @@ enum {
>         HCI_CMD_PENDING,
>         HCI_FORCE_NO_MITM,
>
> +#if IS_ENABLED(CONFIG_BT_OFFLOAD_CODECS)
> +       HCI_OFFLOAD_CODECS_ENABLED,
> +#endif

That is probably a bad idea as it could lead the enum to assume
different values based on what is enabled, besides we don't gain
anything by not having the symbol defined all the time.

> +
>         __HCI_NUM_FLAGS,
>  };
>
> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> index 3663f880df11..d7be85eb52e7 100644
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -3791,6 +3791,14 @@ static const u8 debug_uuid[16] = {
>  };
>  #endif
>
> +#if IS_ENABLED(CONFIG_BT_OFFLOAD_CODECS)
> +/* a6695ace-ee7f-4fb9-881a-5fac66c629af */
> +static const u8 offload_codecs_uuid[16] = {
> +       0xaf, 0x29, 0xc6, 0x66, 0xac, 0x5f, 0x1a, 0x88,
> +       0xb9, 0x4f, 0x7f, 0xee, 0xce, 0x5a, 0x69, 0xa6,
> +};
> +#endif
> +
>  /* 671b10b5-42c0-4696-9227-eb28d1b049d6 */
>  static const u8 simult_central_periph_uuid[16] = {
>         0xd6, 0x49, 0xb0, 0xd1, 0x28, 0xeb, 0x27, 0x92,
> @@ -3806,7 +3814,7 @@ static const u8 rpa_resolution_uuid[16] = {
>  static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev,
>                                   void *data, u16 data_len)
>  {
> -       char buf[62];   /* Enough space for 3 features */
> +       char buf[82];   /* Enough space for 4 features: 2 + 20 * 4 */
>         struct mgmt_rp_read_exp_features_info *rp = (void *)buf;
>         u16 idx = 0;
>         u32 flags;
> @@ -3850,6 +3858,28 @@ static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev,
>                 idx++;
>         }
>
> +#if IS_ENABLED(CONFIG_BT_OFFLOAD_CODECS)
> +       if (hdev) {

If we have HCI_OFFLOAD_CODECS_ENABLED defined you can just use
IS_ENABLED within the if statement below.

> +               if (hdev->get_data_path_id) {
> +                       /* BIT(0): indicating if offload codecs are
> +                        * supported by controller.
> +                        */
> +                       flags = BIT(0);
> +
> +                       /* BIT(1): indicating if codec offload feature
> +                        * is enabled.
> +                        */
> +                       if (hci_dev_test_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED))
> +                               flags |= BIT(1);
> +               } else {
> +                       flags = 0;
> +               }
> +               memcpy(rp->features[idx].uuid, offload_codecs_uuid, 16);
> +               rp->features[idx].flags = cpu_to_le32(flags);
> +               idx++;
> +       }
> +#endif
> +
>         rp->feature_count = cpu_to_le16(idx);
>
>         /* After reading the experimental features information, enable
> @@ -3892,6 +3922,23 @@ static int exp_debug_feature_changed(bool enabled, struct sock *skip)
>  }
>  #endif
>
> +#if IS_ENABLED(CONFIG_BT_OFFLOAD_CODECS)
> +static int exp_offload_codec_feature_changed(bool enabled, struct sock *skip)
> +{
> +       struct mgmt_ev_exp_feature_changed ev;
> +
> +       BT_INFO("enabled %d", enabled);
> +
> +       memset(&ev, 0, sizeof(ev));
> +       memcpy(ev.uuid, offload_codecs_uuid, 16);
> +       ev.flags = cpu_to_le32(enabled ? BIT(0) : 0);
> +
> +       return mgmt_limited_event(MGMT_EV_EXP_FEATURE_CHANGED, NULL,
> +                                 &ev, sizeof(ev),
> +                                 HCI_MGMT_EXP_FEATURE_EVENTS, skip);
> +}
> +#endif
> +
>  static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
>                            void *data, u16 data_len)
>  {
> @@ -4038,6 +4085,63 @@ static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
>                 return err;
>         }
>
> +#if IS_ENABLED(CONFIG_BT_OFFLOAD_CODECS)

Ditto.

> +       if (!memcmp(cp->uuid, offload_codecs_uuid, 16)) {
> +               bool val, changed;
> +               int err;
> +
> +               /* Command requires to use a valid controller index */
> +               if (!hdev)
> +                       return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
> +                                              MGMT_OP_SET_EXP_FEATURE,
> +                                              MGMT_STATUS_INVALID_INDEX);
> +
> +               /* Parameters are limited to a single octet */
> +               if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
> +                       return mgmt_cmd_status(sk, hdev->id,
> +                                              MGMT_OP_SET_EXP_FEATURE,
> +                                              MGMT_STATUS_INVALID_PARAMS);
> +
> +               /* Only boolean on/off is supported */
> +               if (cp->param[0] != 0x00 && cp->param[0] != 0x01)
> +                       return mgmt_cmd_status(sk, hdev->id,
> +                                              MGMT_OP_SET_EXP_FEATURE,
> +                                              MGMT_STATUS_INVALID_PARAMS);
> +
> +               val = !!cp->param[0];
> +               changed = (val != hci_dev_test_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED));
> +
> +               if (!hdev->get_data_path_id) {
> +                       bt_dev_info(hdev, "offload codecs not supported");
> +                       return mgmt_cmd_status(sk, hdev->id,
> +                                              MGMT_OP_SET_EXP_FEATURE,
> +                                              MGMT_STATUS_NOT_SUPPORTED);
> +               }
> +
> +               if (changed) {
> +                       if (val)
> +                               hci_dev_set_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED);
> +                       else
> +                               hci_dev_clear_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED);
> +               }
> +
> +               bt_dev_info(hdev, "offload codecs enable %d changed %d",
> +                           val, changed);
> +
> +               memcpy(rp.uuid, offload_codecs_uuid, 16);
> +               rp.flags = cpu_to_le32(val ? BIT(0) : 0);
> +               hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
> +               err = mgmt_cmd_complete(sk, hdev->id,
> +                                       MGMT_OP_SET_EXP_FEATURE, 0,
> +                                       &rp, sizeof(rp));
> +
> +               if (changed)
> +                       exp_offload_codec_feature_changed(val, sk);
> +
> +               return err;
> +       }
> +#endif
> +
>         return mgmt_cmd_status(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
>                                MGMT_OP_SET_EXP_FEATURE,
>                                MGMT_STATUS_NOT_SUPPORTED);
> diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
> index b44d56eb936a..bc033464af43 100644
> --- a/net/bluetooth/sco.c
> +++ b/net/bluetooth/sco.c
> @@ -964,6 +964,11 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
>                         break;
>                 }
>
> +               if (!hci_dev_test_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED)) {
> +                       err = -EOPNOTSUPP;
> +                       break;
> +               }
> +
>                 if (!hdev->get_codec_config_data) {
>                         err = -EOPNOTSUPP;
>                         break;
> @@ -1163,6 +1168,11 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname,
>                         break;
>                 }
>
> +               if (!hci_dev_test_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED)) {
> +                       err = -EOPNOTSUPP;
> +                       break;
> +               }
> +
>                 if (!hdev->get_data_path_id) {
>                         err = -EOPNOTSUPP;
>                         break;
> --
> 2.17.1
>
Marcel Holtmann July 22, 2021, 2:01 p.m. UTC | #2
Hi Luiz,

>> Allow user level process to enable / disable codec offload
>> feature through mgmt interface. By default offload codec feature
>> is disabled.
>> 
>> Signed-off-by: Kiran K <kiran.k@intel.com>
>> Reviewed-by: Chethan T N <chethan.tumkur.narayan@intel.com>
>> Reviewed-by: Srivatsa Ravishankar <ravishankar.srivatsa@intel.com>
>> ---
>> * changes in v10:
>>  - new patch added to place offload codec feature under experimental flag
>> 
>> include/net/bluetooth/hci.h |   4 ++
>> net/bluetooth/mgmt.c        | 106 +++++++++++++++++++++++++++++++++++-
>> net/bluetooth/sco.c         |  10 ++++
>> 3 files changed, 119 insertions(+), 1 deletion(-)
>> 
>> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
>> index e20318854900..5ca98d9f64dd 100644
>> --- a/include/net/bluetooth/hci.h
>> +++ b/include/net/bluetooth/hci.h
>> @@ -331,6 +331,10 @@ enum {
>>        HCI_CMD_PENDING,
>>        HCI_FORCE_NO_MITM,
>> 
>> +#if IS_ENABLED(CONFIG_BT_OFFLOAD_CODECS)
>> +       HCI_OFFLOAD_CODECS_ENABLED,
>> +#endif
> 
> That is probably a bad idea as it could lead the enum to assume
> different values based on what is enabled, besides we don't gain
> anything by not having the symbol defined all the time.

While this would work with dev_flags which are internal and not API, I still don’t like it.

There is really no benefit to make this a compile time option. And as far as I remember I never said this needs to be compile time. Actually I rather have this as an experimental setting so that it can be switched on at runtime. Nobody is going to recompile their kernels to test codec offload.

Regards

Marcel
Luiz Augusto von Dentz July 22, 2021, 5:42 p.m. UTC | #3
Hi Marcel,

On Thu, Jul 22, 2021 at 7:01 AM Marcel Holtmann <marcel@holtmann.org> wrote:
>
> Hi Luiz,
>
> >> Allow user level process to enable / disable codec offload
> >> feature through mgmt interface. By default offload codec feature
> >> is disabled.
> >>
> >> Signed-off-by: Kiran K <kiran.k@intel.com>
> >> Reviewed-by: Chethan T N <chethan.tumkur.narayan@intel.com>
> >> Reviewed-by: Srivatsa Ravishankar <ravishankar.srivatsa@intel.com>
> >> ---
> >> * changes in v10:
> >>  - new patch added to place offload codec feature under experimental flag
> >>
> >> include/net/bluetooth/hci.h |   4 ++
> >> net/bluetooth/mgmt.c        | 106 +++++++++++++++++++++++++++++++++++-
> >> net/bluetooth/sco.c         |  10 ++++
> >> 3 files changed, 119 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> >> index e20318854900..5ca98d9f64dd 100644
> >> --- a/include/net/bluetooth/hci.h
> >> +++ b/include/net/bluetooth/hci.h
> >> @@ -331,6 +331,10 @@ enum {
> >>        HCI_CMD_PENDING,
> >>        HCI_FORCE_NO_MITM,
> >>
> >> +#if IS_ENABLED(CONFIG_BT_OFFLOAD_CODECS)
> >> +       HCI_OFFLOAD_CODECS_ENABLED,
> >> +#endif
> >
> > That is probably a bad idea as it could lead the enum to assume
> > different values based on what is enabled, besides we don't gain
> > anything by not having the symbol defined all the time.
>
> While this would work with dev_flags which are internal and not API, I still don’t like it.
>
> There is really no benefit to make this a compile time option. And as far as I remember I never said this needs to be compile time. Actually I rather have this as an experimental setting so that it can be switched on at runtime. Nobody is going to recompile their kernels to test codec offload.

Initially I was with the same opinion, but the problem is the codecs
are read at init sequence and the experimental flags are set at a
later stage thus why I suggested a KConfig option until the feature is
more mature and we can remove the option altogether.

> Regards
>
> Marcel
>
Marcel Holtmann July 22, 2021, 5:59 p.m. UTC | #4
Hi Luiz,

>>>> Allow user level process to enable / disable codec offload
>>>> feature through mgmt interface. By default offload codec feature
>>>> is disabled.
>>>> 
>>>> Signed-off-by: Kiran K <kiran.k@intel.com>
>>>> Reviewed-by: Chethan T N <chethan.tumkur.narayan@intel.com>
>>>> Reviewed-by: Srivatsa Ravishankar <ravishankar.srivatsa@intel.com>
>>>> ---
>>>> * changes in v10:
>>>> - new patch added to place offload codec feature under experimental flag
>>>> 
>>>> include/net/bluetooth/hci.h |   4 ++
>>>> net/bluetooth/mgmt.c        | 106 +++++++++++++++++++++++++++++++++++-
>>>> net/bluetooth/sco.c         |  10 ++++
>>>> 3 files changed, 119 insertions(+), 1 deletion(-)
>>>> 
>>>> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
>>>> index e20318854900..5ca98d9f64dd 100644
>>>> --- a/include/net/bluetooth/hci.h
>>>> +++ b/include/net/bluetooth/hci.h
>>>> @@ -331,6 +331,10 @@ enum {
>>>>       HCI_CMD_PENDING,
>>>>       HCI_FORCE_NO_MITM,
>>>> 
>>>> +#if IS_ENABLED(CONFIG_BT_OFFLOAD_CODECS)
>>>> +       HCI_OFFLOAD_CODECS_ENABLED,
>>>> +#endif
>>> 
>>> That is probably a bad idea as it could lead the enum to assume
>>> different values based on what is enabled, besides we don't gain
>>> anything by not having the symbol defined all the time.
>> 
>> While this would work with dev_flags which are internal and not API, I still don’t like it.
>> 
>> There is really no benefit to make this a compile time option. And as far as I remember I never said this needs to be compile time. Actually I rather have this as an experimental setting so that it can be switched on at runtime. Nobody is going to recompile their kernels to test codec offload.
> 
> Initially I was with the same opinion, but the problem is the codecs
> are read at init sequence and the experimental flags are set at a
> later stage thus why I suggested a KConfig option until the feature is
> more mature and we can remove the option altogether.

I am fine with the codec options being read all the time. I mean having an experimental option to control the use of offload.

Regards

Marcel
Luiz Augusto von Dentz July 22, 2021, 6:07 p.m. UTC | #5
Hi Marcel,

On Thu, Jul 22, 2021 at 10:59 AM Marcel Holtmann <marcel@holtmann.org> wrote:
>
> Hi Luiz,
>
> >>>> Allow user level process to enable / disable codec offload
> >>>> feature through mgmt interface. By default offload codec feature
> >>>> is disabled.
> >>>>
> >>>> Signed-off-by: Kiran K <kiran.k@intel.com>
> >>>> Reviewed-by: Chethan T N <chethan.tumkur.narayan@intel.com>
> >>>> Reviewed-by: Srivatsa Ravishankar <ravishankar.srivatsa@intel.com>
> >>>> ---
> >>>> * changes in v10:
> >>>> - new patch added to place offload codec feature under experimental flag
> >>>>
> >>>> include/net/bluetooth/hci.h |   4 ++
> >>>> net/bluetooth/mgmt.c        | 106 +++++++++++++++++++++++++++++++++++-
> >>>> net/bluetooth/sco.c         |  10 ++++
> >>>> 3 files changed, 119 insertions(+), 1 deletion(-)
> >>>>
> >>>> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> >>>> index e20318854900..5ca98d9f64dd 100644
> >>>> --- a/include/net/bluetooth/hci.h
> >>>> +++ b/include/net/bluetooth/hci.h
> >>>> @@ -331,6 +331,10 @@ enum {
> >>>>       HCI_CMD_PENDING,
> >>>>       HCI_FORCE_NO_MITM,
> >>>>
> >>>> +#if IS_ENABLED(CONFIG_BT_OFFLOAD_CODECS)
> >>>> +       HCI_OFFLOAD_CODECS_ENABLED,
> >>>> +#endif
> >>>
> >>> That is probably a bad idea as it could lead the enum to assume
> >>> different values based on what is enabled, besides we don't gain
> >>> anything by not having the symbol defined all the time.
> >>
> >> While this would work with dev_flags which are internal and not API, I still don’t like it.
> >>
> >> There is really no benefit to make this a compile time option. And as far as I remember I never said this needs to be compile time. Actually I rather have this as an experimental setting so that it can be switched on at runtime. Nobody is going to recompile their kernels to test codec offload.
> >
> > Initially I was with the same opinion, but the problem is the codecs
> > are read at init sequence and the experimental flags are set at a
> > later stage thus why I suggested a KConfig option until the feature is
> > more mature and we can remove the option altogether.
>
> I am fine with the codec options being read all the time. I mean having an experimental option to control the use of offload.

Alright, then we don't need the Kconfig after all, the experimental
flag will only control the use of the codecs e.g. socketopts would not
work if the flag is not enabled I assume?

> Regards
>
> Marcel
>
Marcel Holtmann July 22, 2021, 6:50 p.m. UTC | #6
Hi Luiz,

>>>>>> Allow user level process to enable / disable codec offload
>>>>>> feature through mgmt interface. By default offload codec feature
>>>>>> is disabled.
>>>>>> 
>>>>>> Signed-off-by: Kiran K <kiran.k@intel.com>
>>>>>> Reviewed-by: Chethan T N <chethan.tumkur.narayan@intel.com>
>>>>>> Reviewed-by: Srivatsa Ravishankar <ravishankar.srivatsa@intel.com>
>>>>>> ---
>>>>>> * changes in v10:
>>>>>> - new patch added to place offload codec feature under experimental flag
>>>>>> 
>>>>>> include/net/bluetooth/hci.h |   4 ++
>>>>>> net/bluetooth/mgmt.c        | 106 +++++++++++++++++++++++++++++++++++-
>>>>>> net/bluetooth/sco.c         |  10 ++++
>>>>>> 3 files changed, 119 insertions(+), 1 deletion(-)
>>>>>> 
>>>>>> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
>>>>>> index e20318854900..5ca98d9f64dd 100644
>>>>>> --- a/include/net/bluetooth/hci.h
>>>>>> +++ b/include/net/bluetooth/hci.h
>>>>>> @@ -331,6 +331,10 @@ enum {
>>>>>>      HCI_CMD_PENDING,
>>>>>>      HCI_FORCE_NO_MITM,
>>>>>> 
>>>>>> +#if IS_ENABLED(CONFIG_BT_OFFLOAD_CODECS)
>>>>>> +       HCI_OFFLOAD_CODECS_ENABLED,
>>>>>> +#endif
>>>>> 
>>>>> That is probably a bad idea as it could lead the enum to assume
>>>>> different values based on what is enabled, besides we don't gain
>>>>> anything by not having the symbol defined all the time.
>>>> 
>>>> While this would work with dev_flags which are internal and not API, I still don’t like it.
>>>> 
>>>> There is really no benefit to make this a compile time option. And as far as I remember I never said this needs to be compile time. Actually I rather have this as an experimental setting so that it can be switched on at runtime. Nobody is going to recompile their kernels to test codec offload.
>>> 
>>> Initially I was with the same opinion, but the problem is the codecs
>>> are read at init sequence and the experimental flags are set at a
>>> later stage thus why I suggested a KConfig option until the feature is
>>> more mature and we can remove the option altogether.
>> 
>> I am fine with the codec options being read all the time. I mean having an experimental option to control the use of offload.
> 
> Alright, then we don't need the Kconfig after all, the experimental
> flag will only control the use of the codecs e.g. socketopts would not
> work if the flag is not enabled I assume?

exactly. It would then return EOPNOTSUPP error. It would be similar to an old kernel where this socket option is not available either.

Regards

Marcel
K, Kiran July 27, 2021, 7:21 a.m. UTC | #7
Hi Luiz, Marcel,

> -----Original Message-----
> From: Marcel Holtmann <marcel@holtmann.org>
> Sent: Friday, July 23, 2021 12:21 AM
> To: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
> Cc: K, Kiran <kiran.k@intel.com>; linux-bluetooth@vger.kernel.org
> Subject: Re: [PATCH v10 10/10] Bluetooth: Add offload feature under
> experimental flag
> 
> Hi Luiz,
> 
> >>>>>> Allow user level process to enable / disable codec offload
> >>>>>> feature through mgmt interface. By default offload codec feature
> >>>>>> is disabled.
> >>>>>>
> >>>>>> Signed-off-by: Kiran K <kiran.k@intel.com>
> >>>>>> Reviewed-by: Chethan T N <chethan.tumkur.narayan@intel.com>
> >>>>>> Reviewed-by: Srivatsa Ravishankar
> >>>>>> <ravishankar.srivatsa@intel.com>
> >>>>>> ---
> >>>>>> * changes in v10:
> >>>>>> - new patch added to place offload codec feature under
> >>>>>> experimental flag
> >>>>>>
> >>>>>> include/net/bluetooth/hci.h |   4 ++
> >>>>>> net/bluetooth/mgmt.c        | 106
> +++++++++++++++++++++++++++++++++++-
> >>>>>> net/bluetooth/sco.c         |  10 ++++
> >>>>>> 3 files changed, 119 insertions(+), 1 deletion(-)
> >>>>>>
> >>>>>> diff --git a/include/net/bluetooth/hci.h
> >>>>>> b/include/net/bluetooth/hci.h index e20318854900..5ca98d9f64dd
> >>>>>> 100644
> >>>>>> --- a/include/net/bluetooth/hci.h
> >>>>>> +++ b/include/net/bluetooth/hci.h
> >>>>>> @@ -331,6 +331,10 @@ enum {
> >>>>>>      HCI_CMD_PENDING,
> >>>>>>      HCI_FORCE_NO_MITM,
> >>>>>>
> >>>>>> +#if IS_ENABLED(CONFIG_BT_OFFLOAD_CODECS)
> >>>>>> +       HCI_OFFLOAD_CODECS_ENABLED, #endif
> >>>>>
> >>>>> That is probably a bad idea as it could lead the enum to assume
> >>>>> different values based on what is enabled, besides we don't gain
> >>>>> anything by not having the symbol defined all the time.
> >>>>
> >>>> While this would work with dev_flags which are internal and not API, I
> still don’t like it.
> >>>>
> >>>> There is really no benefit to make this a compile time option. And as far
> as I remember I never said this needs to be compile time. Actually I rather
> have this as an experimental setting so that it can be switched on at runtime.
> Nobody is going to recompile their kernels to test codec offload.
> >>>
> >>> Initially I was with the same opinion, but the problem is the codecs
> >>> are read at init sequence and the experimental flags are set at a
> >>> later stage thus why I suggested a KConfig option until the feature
> >>> is more mature and we can remove the option altogether.
> >>
> >> I am fine with the codec options being read all the time. I mean having an
> experimental option to control the use of offload.
> >
> > Alright, then we don't need the Kconfig after all, the experimental
> > flag will only control the use of the codecs e.g. socketopts would not
> > work if the flag is not enabled I assume?
> 
> exactly. It would then return EOPNOTSUPP error. It would be similar to an old
> kernel where this socket option is not available either.

Ack. I will send the changes in the next patchset.

> 
> Regards
> 
> Marcel

Regards,
Kiran
diff mbox series

Patch

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index e20318854900..5ca98d9f64dd 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -331,6 +331,10 @@  enum {
 	HCI_CMD_PENDING,
 	HCI_FORCE_NO_MITM,
 
+#if IS_ENABLED(CONFIG_BT_OFFLOAD_CODECS)
+	HCI_OFFLOAD_CODECS_ENABLED,
+#endif
+
 	__HCI_NUM_FLAGS,
 };
 
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 3663f880df11..d7be85eb52e7 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3791,6 +3791,14 @@  static const u8 debug_uuid[16] = {
 };
 #endif
 
+#if IS_ENABLED(CONFIG_BT_OFFLOAD_CODECS)
+/* a6695ace-ee7f-4fb9-881a-5fac66c629af */
+static const u8 offload_codecs_uuid[16] = {
+	0xaf, 0x29, 0xc6, 0x66, 0xac, 0x5f, 0x1a, 0x88,
+	0xb9, 0x4f, 0x7f, 0xee, 0xce, 0x5a, 0x69, 0xa6,
+};
+#endif
+
 /* 671b10b5-42c0-4696-9227-eb28d1b049d6 */
 static const u8 simult_central_periph_uuid[16] = {
 	0xd6, 0x49, 0xb0, 0xd1, 0x28, 0xeb, 0x27, 0x92,
@@ -3806,7 +3814,7 @@  static const u8 rpa_resolution_uuid[16] = {
 static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev,
 				  void *data, u16 data_len)
 {
-	char buf[62];	/* Enough space for 3 features */
+	char buf[82];   /* Enough space for 4 features: 2 + 20 * 4 */
 	struct mgmt_rp_read_exp_features_info *rp = (void *)buf;
 	u16 idx = 0;
 	u32 flags;
@@ -3850,6 +3858,28 @@  static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev,
 		idx++;
 	}
 
+#if IS_ENABLED(CONFIG_BT_OFFLOAD_CODECS)
+	if (hdev) {
+		if (hdev->get_data_path_id) {
+			/* BIT(0): indicating if offload codecs are
+			 * supported by controller.
+			 */
+			flags = BIT(0);
+
+			/* BIT(1): indicating if codec offload feature
+			 * is enabled.
+			 */
+			if (hci_dev_test_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED))
+				flags |= BIT(1);
+		} else {
+			flags = 0;
+		}
+		memcpy(rp->features[idx].uuid, offload_codecs_uuid, 16);
+		rp->features[idx].flags = cpu_to_le32(flags);
+		idx++;
+	}
+#endif
+
 	rp->feature_count = cpu_to_le16(idx);
 
 	/* After reading the experimental features information, enable
@@ -3892,6 +3922,23 @@  static int exp_debug_feature_changed(bool enabled, struct sock *skip)
 }
 #endif
 
+#if IS_ENABLED(CONFIG_BT_OFFLOAD_CODECS)
+static int exp_offload_codec_feature_changed(bool enabled, struct sock *skip)
+{
+	struct mgmt_ev_exp_feature_changed ev;
+
+	BT_INFO("enabled %d", enabled);
+
+	memset(&ev, 0, sizeof(ev));
+	memcpy(ev.uuid, offload_codecs_uuid, 16);
+	ev.flags = cpu_to_le32(enabled ? BIT(0) : 0);
+
+	return mgmt_limited_event(MGMT_EV_EXP_FEATURE_CHANGED, NULL,
+				  &ev, sizeof(ev),
+				  HCI_MGMT_EXP_FEATURE_EVENTS, skip);
+}
+#endif
+
 static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
 			   void *data, u16 data_len)
 {
@@ -4038,6 +4085,63 @@  static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
 		return err;
 	}
 
+#if IS_ENABLED(CONFIG_BT_OFFLOAD_CODECS)
+	if (!memcmp(cp->uuid, offload_codecs_uuid, 16)) {
+		bool val, changed;
+		int err;
+
+		/* Command requires to use a valid controller index */
+		if (!hdev)
+			return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
+					       MGMT_OP_SET_EXP_FEATURE,
+					       MGMT_STATUS_INVALID_INDEX);
+
+		/* Parameters are limited to a single octet */
+		if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
+			return mgmt_cmd_status(sk, hdev->id,
+					       MGMT_OP_SET_EXP_FEATURE,
+					       MGMT_STATUS_INVALID_PARAMS);
+
+		/* Only boolean on/off is supported */
+		if (cp->param[0] != 0x00 && cp->param[0] != 0x01)
+			return mgmt_cmd_status(sk, hdev->id,
+					       MGMT_OP_SET_EXP_FEATURE,
+					       MGMT_STATUS_INVALID_PARAMS);
+
+		val = !!cp->param[0];
+		changed = (val != hci_dev_test_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED));
+
+		if (!hdev->get_data_path_id) {
+			bt_dev_info(hdev, "offload codecs not supported");
+			return mgmt_cmd_status(sk, hdev->id,
+					       MGMT_OP_SET_EXP_FEATURE,
+					       MGMT_STATUS_NOT_SUPPORTED);
+		}
+
+		if (changed) {
+			if (val)
+				hci_dev_set_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED);
+			else
+				hci_dev_clear_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED);
+		}
+
+		bt_dev_info(hdev, "offload codecs enable %d changed %d",
+			    val, changed);
+
+		memcpy(rp.uuid, offload_codecs_uuid, 16);
+		rp.flags = cpu_to_le32(val ? BIT(0) : 0);
+		hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
+		err = mgmt_cmd_complete(sk, hdev->id,
+					MGMT_OP_SET_EXP_FEATURE, 0,
+					&rp, sizeof(rp));
+
+		if (changed)
+			exp_offload_codec_feature_changed(val, sk);
+
+		return err;
+	}
+#endif
+
 	return mgmt_cmd_status(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
 			       MGMT_OP_SET_EXP_FEATURE,
 			       MGMT_STATUS_NOT_SUPPORTED);
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index b44d56eb936a..bc033464af43 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -964,6 +964,11 @@  static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
 			break;
 		}
 
+		if (!hci_dev_test_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED)) {
+			err = -EOPNOTSUPP;
+			break;
+		}
+
 		if (!hdev->get_codec_config_data) {
 			err = -EOPNOTSUPP;
 			break;
@@ -1163,6 +1168,11 @@  static int sco_sock_getsockopt(struct socket *sock, int level, int optname,
 			break;
 		}
 
+		if (!hci_dev_test_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED)) {
+			err = -EOPNOTSUPP;
+			break;
+		}
+
 		if (!hdev->get_data_path_id) {
 			err = -EOPNOTSUPP;
 			break;