Linux 6.9-rc1
[linux-2.6-microblaze.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_OR_NULL(skb)) {
58                 if (!skb)
59                         skb = ERR_PTR(-EIO);
60
61                 bt_dev_err(hdev, "AOSP get vendor capabilities (%ld)",
62                            PTR_ERR(skb));
63                 return;
64         }
65
66         /* A basic length check */
67         if (skb->len < VENDOR_CAPA_BASE_SIZE)
68                 goto length_error;
69
70         rp = (struct aosp_rp_le_get_vendor_capa *)skb->data;
71
72         version_supported = le16_to_cpu(rp->version_supported);
73         /* AOSP displays the verion number like v0.98, v1.00, etc. */
74         bt_dev_info(hdev, "AOSP extensions version v%u.%02u",
75                     version_supported >> 8, version_supported & 0xff);
76
77         /* Do not support very old versions. */
78         if (version_supported < 95) {
79                 bt_dev_warn(hdev, "AOSP capabilities version %u too old",
80                             version_supported);
81                 goto done;
82         }
83
84         if (version_supported < 98) {
85                 bt_dev_warn(hdev, "AOSP quality report is not supported");
86                 goto done;
87         }
88
89         if (skb->len < VENDOR_CAPA_0_98_SIZE)
90                 goto length_error;
91
92         /* The bluetooth_quality_report_support is defined at version
93          * v0.98. Refer to
94          * https://cs.android.com/android/platform/superproject/+/
95          *         master:system/bt/gd/hci/controller.cc;l=477
96          */
97         if (rp->bluetooth_quality_report_support) {
98                 hdev->aosp_quality_report = true;
99                 bt_dev_info(hdev, "AOSP quality report is supported");
100         }
101
102         goto done;
103
104 length_error:
105         bt_dev_err(hdev, "AOSP capabilities length %d too short", skb->len);
106
107 done:
108         kfree_skb(skb);
109 }
110
111 void aosp_do_close(struct hci_dev *hdev)
112 {
113         if (!hdev->aosp_capable)
114                 return;
115
116         bt_dev_dbg(hdev, "Cleanup of AOSP extension");
117 }
118
119 /* BQR command */
120 #define BQR_OPCODE                      hci_opcode_pack(0x3f, 0x015e)
121
122 /* BQR report action */
123 #define REPORT_ACTION_ADD               0x00
124 #define REPORT_ACTION_DELETE            0x01
125 #define REPORT_ACTION_CLEAR             0x02
126
127 /* BQR event masks */
128 #define QUALITY_MONITORING              BIT(0)
129 #define APPRAOCHING_LSTO                BIT(1)
130 #define A2DP_AUDIO_CHOPPY               BIT(2)
131 #define SCO_VOICE_CHOPPY                BIT(3)
132
133 #define DEFAULT_BQR_EVENT_MASK  (QUALITY_MONITORING | APPRAOCHING_LSTO | \
134                                  A2DP_AUDIO_CHOPPY | SCO_VOICE_CHOPPY)
135
136 /* Reporting at milliseconds so as not to stress the controller too much.
137  * Range: 0 ~ 65535 ms
138  */
139 #define DEFALUT_REPORT_INTERVAL_MS      5000
140
141 struct aosp_bqr_cp {
142         __u8    report_action;
143         __u32   event_mask;
144         __u16   min_report_interval;
145 } __packed;
146
147 static int enable_quality_report(struct hci_dev *hdev)
148 {
149         struct sk_buff *skb;
150         struct aosp_bqr_cp cp;
151
152         cp.report_action = REPORT_ACTION_ADD;
153         cp.event_mask = DEFAULT_BQR_EVENT_MASK;
154         cp.min_report_interval = DEFALUT_REPORT_INTERVAL_MS;
155
156         skb = __hci_cmd_sync(hdev, BQR_OPCODE, sizeof(cp), &cp,
157                              HCI_CMD_TIMEOUT);
158         if (IS_ERR_OR_NULL(skb)) {
159                 if (!skb)
160                         skb = ERR_PTR(-EIO);
161
162                 bt_dev_err(hdev, "Enabling Android BQR failed (%ld)",
163                            PTR_ERR(skb));
164                 return PTR_ERR(skb);
165         }
166
167         kfree_skb(skb);
168         return 0;
169 }
170
171 static int disable_quality_report(struct hci_dev *hdev)
172 {
173         struct sk_buff *skb;
174         struct aosp_bqr_cp cp = { 0 };
175
176         cp.report_action = REPORT_ACTION_CLEAR;
177
178         skb = __hci_cmd_sync(hdev, BQR_OPCODE, sizeof(cp), &cp,
179                              HCI_CMD_TIMEOUT);
180         if (IS_ERR_OR_NULL(skb)) {
181                 if (!skb)
182                         skb = ERR_PTR(-EIO);
183
184                 bt_dev_err(hdev, "Disabling Android BQR failed (%ld)",
185                            PTR_ERR(skb));
186                 return PTR_ERR(skb);
187         }
188
189         kfree_skb(skb);
190         return 0;
191 }
192
193 bool aosp_has_quality_report(struct hci_dev *hdev)
194 {
195         return hdev->aosp_quality_report;
196 }
197
198 int aosp_set_quality_report(struct hci_dev *hdev, bool enable)
199 {
200         if (!aosp_has_quality_report(hdev))
201                 return -EOPNOTSUPP;
202
203         bt_dev_dbg(hdev, "quality report enable %d", enable);
204
205         /* Enable or disable the quality report feature. */
206         if (enable)
207                 return enable_quality_report(hdev);
208         else
209                 return disable_quality_report(hdev);
210 }