Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/net/bluetooth/aosp.c
26278 views
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 version 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
}
211
212