blob: 432ae3aac9e31d60375f60f81a604f8fed3c944c [file] [log] [blame]
Marcel Holtmannf67743f2021-04-06 21:55:52 +02001// 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
Joseph Hwang749a6c52021-11-02 15:19:28 +080011/* 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 */
17struct 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
Marcel Holtmannf67743f2021-04-06 21:55:52 +020043void aosp_do_open(struct hci_dev *hdev)
44{
45 struct sk_buff *skb;
Joseph Hwang749a6c52021-11-02 15:19:28 +080046 struct aosp_rp_le_get_vendor_capa *rp;
47 u16 version_supported;
Marcel Holtmannf67743f2021-04-06 21:55:52 +020048
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);
Joseph Hwang749a6c52021-11-02 15:19:28 +080057 if (IS_ERR(skb)) {
58 bt_dev_err(hdev, "AOSP get vendor capabilities (%ld)",
59 PTR_ERR(skb));
Marcel Holtmannf67743f2021-04-06 21:55:52 +020060 return;
Joseph Hwang749a6c52021-11-02 15:19:28 +080061 }
Marcel Holtmannf67743f2021-04-06 21:55:52 +020062
Joseph Hwang749a6c52021-11-02 15:19:28 +080063 /* 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
101length_error:
102 bt_dev_err(hdev, "AOSP capabilities length %d too short", skb->len);
103
104done:
Marcel Holtmannf67743f2021-04-06 21:55:52 +0200105 kfree_skb(skb);
106}
107
108void 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}
Joseph Hwang258f56d2021-11-02 15:19:29 +0800115
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
138struct aosp_bqr_cp {
139 __u8 report_action;
140 __u32 event_mask;
141 __u16 min_report_interval;
142} __packed;
143
144static 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
165static 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
184bool aosp_has_quality_report(struct hci_dev *hdev)
185{
186 return hdev->aosp_quality_report;
187}
188
189int 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}