Merge tag 'net-5.18-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
[platform/kernel/linux-starfive.git] / net / bluetooth / aosp.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2021 Intel Corporation
4  */
5
6 #include <net/bluetooth/bluetooth.h>
7 #include <net/bluetooth/hci_core.h>
8
9 #include "aosp.h"
10
11 /* Command complete parameters of LE_Get_Vendor_Capabilities_Command
12  * The parameters grow over time. The base version that declares the
13  * version_supported field is v0.95. Refer to
14  * https://cs.android.com/android/platform/superproject/+/master:system/
15  *         bt/gd/hci/controller.cc;l=452?q=le_get_vendor_capabilities_handler
16  */
17 struct aosp_rp_le_get_vendor_capa {
18         /* v0.95: 15 octets */
19         __u8    status;
20         __u8    max_advt_instances;
21         __u8    offloaded_resolution_of_private_address;
22         __le16  total_scan_results_storage;
23         __u8    max_irk_list_sz;
24         __u8    filtering_support;
25         __u8    max_filter;
26         __u8    activity_energy_info_support;
27         __le16  version_supported;
28         __le16  total_num_of_advt_tracked;
29         __u8    extended_scan_support;
30         __u8    debug_logging_supported;
31         /* v0.96: 16 octets */
32         __u8    le_address_generation_offloading_support;
33         /* v0.98: 21 octets */
34         __le32  a2dp_source_offload_capability_mask;
35         __u8    bluetooth_quality_report_support;
36         /* v1.00: 25 octets */
37         __le32  dynamic_audio_buffer_support;
38 } __packed;
39
40 #define VENDOR_CAPA_BASE_SIZE           15
41 #define VENDOR_CAPA_0_98_SIZE           21
42
43 void aosp_do_open(struct hci_dev *hdev)
44 {
45         struct sk_buff *skb;
46         struct aosp_rp_le_get_vendor_capa *rp;
47         u16 version_supported;
48
49         if (!hdev->aosp_capable)
50                 return;
51
52         bt_dev_dbg(hdev, "Initialize AOSP extension");
53
54         /* LE Get Vendor Capabilities Command */
55         skb = __hci_cmd_sync(hdev, hci_opcode_pack(0x3f, 0x153), 0, NULL,
56                              HCI_CMD_TIMEOUT);
57         if (IS_ERR(skb)) {
58                 bt_dev_err(hdev, "AOSP get vendor capabilities (%ld)",
59                            PTR_ERR(skb));
60                 return;
61         }
62
63         /* A basic length check */
64         if (skb->len < VENDOR_CAPA_BASE_SIZE)
65                 goto length_error;
66
67         rp = (struct aosp_rp_le_get_vendor_capa *)skb->data;
68
69         version_supported = le16_to_cpu(rp->version_supported);
70         /* AOSP displays the verion number like v0.98, v1.00, etc. */
71         bt_dev_info(hdev, "AOSP extensions version v%u.%02u",
72                     version_supported >> 8, version_supported & 0xff);
73
74         /* Do not support very old versions. */
75         if (version_supported < 95) {
76                 bt_dev_warn(hdev, "AOSP capabilities version %u too old",
77                             version_supported);
78                 goto done;
79         }
80
81         if (version_supported < 98) {
82                 bt_dev_warn(hdev, "AOSP quality report is not supported");
83                 goto done;
84         }
85
86         if (skb->len < VENDOR_CAPA_0_98_SIZE)
87                 goto length_error;
88
89         /* The bluetooth_quality_report_support is defined at version
90          * v0.98. Refer to
91          * https://cs.android.com/android/platform/superproject/+/
92          *         master:system/bt/gd/hci/controller.cc;l=477
93          */
94         if (rp->bluetooth_quality_report_support) {
95                 hdev->aosp_quality_report = true;
96                 bt_dev_info(hdev, "AOSP quality report is supported");
97         }
98
99         goto done;
100
101 length_error:
102         bt_dev_err(hdev, "AOSP capabilities length %d too short", skb->len);
103
104 done:
105         kfree_skb(skb);
106 }
107
108 void aosp_do_close(struct hci_dev *hdev)
109 {
110         if (!hdev->aosp_capable)
111                 return;
112
113         bt_dev_dbg(hdev, "Cleanup of AOSP extension");
114 }
115
116 /* BQR command */
117 #define BQR_OPCODE                      hci_opcode_pack(0x3f, 0x015e)
118
119 /* BQR report action */
120 #define REPORT_ACTION_ADD               0x00
121 #define REPORT_ACTION_DELETE            0x01
122 #define REPORT_ACTION_CLEAR             0x02
123
124 /* BQR event masks */
125 #define QUALITY_MONITORING              BIT(0)
126 #define APPRAOCHING_LSTO                BIT(1)
127 #define A2DP_AUDIO_CHOPPY               BIT(2)
128 #define SCO_VOICE_CHOPPY                BIT(3)
129
130 #define DEFAULT_BQR_EVENT_MASK  (QUALITY_MONITORING | APPRAOCHING_LSTO | \
131                                  A2DP_AUDIO_CHOPPY | SCO_VOICE_CHOPPY)
132
133 /* Reporting at milliseconds so as not to stress the controller too much.
134  * Range: 0 ~ 65535 ms
135  */
136 #define DEFALUT_REPORT_INTERVAL_MS      5000
137
138 struct aosp_bqr_cp {
139         __u8    report_action;
140         __u32   event_mask;
141         __u16   min_report_interval;
142 } __packed;
143
144 static int enable_quality_report(struct hci_dev *hdev)
145 {
146         struct sk_buff *skb;
147         struct aosp_bqr_cp cp;
148
149         cp.report_action = REPORT_ACTION_ADD;
150         cp.event_mask = DEFAULT_BQR_EVENT_MASK;
151         cp.min_report_interval = DEFALUT_REPORT_INTERVAL_MS;
152
153         skb = __hci_cmd_sync(hdev, BQR_OPCODE, sizeof(cp), &cp,
154                              HCI_CMD_TIMEOUT);
155         if (IS_ERR(skb)) {
156                 bt_dev_err(hdev, "Enabling Android BQR failed (%ld)",
157                            PTR_ERR(skb));
158                 return PTR_ERR(skb);
159         }
160
161         kfree_skb(skb);
162         return 0;
163 }
164
165 static int disable_quality_report(struct hci_dev *hdev)
166 {
167         struct sk_buff *skb;
168         struct aosp_bqr_cp cp = { 0 };
169
170         cp.report_action = REPORT_ACTION_CLEAR;
171
172         skb = __hci_cmd_sync(hdev, BQR_OPCODE, sizeof(cp), &cp,
173                              HCI_CMD_TIMEOUT);
174         if (IS_ERR(skb)) {
175                 bt_dev_err(hdev, "Disabling Android BQR failed (%ld)",
176                            PTR_ERR(skb));
177                 return PTR_ERR(skb);
178         }
179
180         kfree_skb(skb);
181         return 0;
182 }
183
184 bool aosp_has_quality_report(struct hci_dev *hdev)
185 {
186         return hdev->aosp_quality_report;
187 }
188
189 int aosp_set_quality_report(struct hci_dev *hdev, bool enable)
190 {
191         if (!aosp_has_quality_report(hdev))
192                 return -EOPNOTSUPP;
193
194         bt_dev_dbg(hdev, "quality report enable %d", enable);
195
196         /* Enable or disable the quality report feature. */
197         if (enable)
198                 return enable_quality_report(hdev);
199         else
200                 return disable_quality_report(hdev);
201 }