xref: /openbmc/linux/net/bluetooth/aosp.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1f67743f9SMarcel Holtmann // SPDX-License-Identifier: GPL-2.0-only
2f67743f9SMarcel Holtmann /*
3f67743f9SMarcel Holtmann  * Copyright (C) 2021 Intel Corporation
4f67743f9SMarcel Holtmann  */
5f67743f9SMarcel Holtmann 
6f67743f9SMarcel Holtmann #include <net/bluetooth/bluetooth.h>
7f67743f9SMarcel Holtmann #include <net/bluetooth/hci_core.h>
8f67743f9SMarcel Holtmann 
9f67743f9SMarcel Holtmann #include "aosp.h"
10f67743f9SMarcel Holtmann 
11749a6c59SJoseph Hwang /* Command complete parameters of LE_Get_Vendor_Capabilities_Command
12749a6c59SJoseph Hwang  * The parameters grow over time. The base version that declares the
13749a6c59SJoseph Hwang  * version_supported field is v0.95. Refer to
14749a6c59SJoseph Hwang  * https://cs.android.com/android/platform/superproject/+/master:system/
15749a6c59SJoseph Hwang  *         bt/gd/hci/controller.cc;l=452?q=le_get_vendor_capabilities_handler
16749a6c59SJoseph Hwang  */
17749a6c59SJoseph Hwang struct aosp_rp_le_get_vendor_capa {
18749a6c59SJoseph Hwang 	/* v0.95: 15 octets */
19749a6c59SJoseph Hwang 	__u8	status;
20749a6c59SJoseph Hwang 	__u8	max_advt_instances;
21749a6c59SJoseph Hwang 	__u8	offloaded_resolution_of_private_address;
22749a6c59SJoseph Hwang 	__le16	total_scan_results_storage;
23749a6c59SJoseph Hwang 	__u8	max_irk_list_sz;
24749a6c59SJoseph Hwang 	__u8	filtering_support;
25749a6c59SJoseph Hwang 	__u8	max_filter;
26749a6c59SJoseph Hwang 	__u8	activity_energy_info_support;
27749a6c59SJoseph Hwang 	__le16	version_supported;
28749a6c59SJoseph Hwang 	__le16	total_num_of_advt_tracked;
29749a6c59SJoseph Hwang 	__u8	extended_scan_support;
30749a6c59SJoseph Hwang 	__u8	debug_logging_supported;
31749a6c59SJoseph Hwang 	/* v0.96: 16 octets */
32749a6c59SJoseph Hwang 	__u8	le_address_generation_offloading_support;
33749a6c59SJoseph Hwang 	/* v0.98: 21 octets */
34749a6c59SJoseph Hwang 	__le32	a2dp_source_offload_capability_mask;
35749a6c59SJoseph Hwang 	__u8	bluetooth_quality_report_support;
36749a6c59SJoseph Hwang 	/* v1.00: 25 octets */
37749a6c59SJoseph Hwang 	__le32	dynamic_audio_buffer_support;
38749a6c59SJoseph Hwang } __packed;
39749a6c59SJoseph Hwang 
40749a6c59SJoseph Hwang #define VENDOR_CAPA_BASE_SIZE		15
41749a6c59SJoseph Hwang #define VENDOR_CAPA_0_98_SIZE		21
42749a6c59SJoseph Hwang 
aosp_do_open(struct hci_dev * hdev)43f67743f9SMarcel Holtmann void aosp_do_open(struct hci_dev *hdev)
44f67743f9SMarcel Holtmann {
45f67743f9SMarcel Holtmann 	struct sk_buff *skb;
46749a6c59SJoseph Hwang 	struct aosp_rp_le_get_vendor_capa *rp;
47749a6c59SJoseph Hwang 	u16 version_supported;
48f67743f9SMarcel Holtmann 
49f67743f9SMarcel Holtmann 	if (!hdev->aosp_capable)
50f67743f9SMarcel Holtmann 		return;
51f67743f9SMarcel Holtmann 
52f67743f9SMarcel Holtmann 	bt_dev_dbg(hdev, "Initialize AOSP extension");
53f67743f9SMarcel Holtmann 
54f67743f9SMarcel Holtmann 	/* LE Get Vendor Capabilities Command */
55f67743f9SMarcel Holtmann 	skb = __hci_cmd_sync(hdev, hci_opcode_pack(0x3f, 0x153), 0, NULL,
56f67743f9SMarcel Holtmann 			     HCI_CMD_TIMEOUT);
57*ce78e557SSoenke Huster 	if (IS_ERR_OR_NULL(skb)) {
58*ce78e557SSoenke Huster 		if (!skb)
59*ce78e557SSoenke Huster 			skb = ERR_PTR(-EIO);
60*ce78e557SSoenke Huster 
61749a6c59SJoseph Hwang 		bt_dev_err(hdev, "AOSP get vendor capabilities (%ld)",
62749a6c59SJoseph Hwang 			   PTR_ERR(skb));
63f67743f9SMarcel Holtmann 		return;
64749a6c59SJoseph Hwang 	}
65f67743f9SMarcel Holtmann 
66749a6c59SJoseph Hwang 	/* A basic length check */
67749a6c59SJoseph Hwang 	if (skb->len < VENDOR_CAPA_BASE_SIZE)
68749a6c59SJoseph Hwang 		goto length_error;
69749a6c59SJoseph Hwang 
70749a6c59SJoseph Hwang 	rp = (struct aosp_rp_le_get_vendor_capa *)skb->data;
71749a6c59SJoseph Hwang 
72749a6c59SJoseph Hwang 	version_supported = le16_to_cpu(rp->version_supported);
73749a6c59SJoseph Hwang 	/* AOSP displays the verion number like v0.98, v1.00, etc. */
74749a6c59SJoseph Hwang 	bt_dev_info(hdev, "AOSP extensions version v%u.%02u",
75749a6c59SJoseph Hwang 		    version_supported >> 8, version_supported & 0xff);
76749a6c59SJoseph Hwang 
77749a6c59SJoseph Hwang 	/* Do not support very old versions. */
78749a6c59SJoseph Hwang 	if (version_supported < 95) {
79749a6c59SJoseph Hwang 		bt_dev_warn(hdev, "AOSP capabilities version %u too old",
80749a6c59SJoseph Hwang 			    version_supported);
81749a6c59SJoseph Hwang 		goto done;
82749a6c59SJoseph Hwang 	}
83749a6c59SJoseph Hwang 
84749a6c59SJoseph Hwang 	if (version_supported < 98) {
85749a6c59SJoseph Hwang 		bt_dev_warn(hdev, "AOSP quality report is not supported");
86749a6c59SJoseph Hwang 		goto done;
87749a6c59SJoseph Hwang 	}
88749a6c59SJoseph Hwang 
89749a6c59SJoseph Hwang 	if (skb->len < VENDOR_CAPA_0_98_SIZE)
90749a6c59SJoseph Hwang 		goto length_error;
91749a6c59SJoseph Hwang 
92749a6c59SJoseph Hwang 	/* The bluetooth_quality_report_support is defined at version
93749a6c59SJoseph Hwang 	 * v0.98. Refer to
94749a6c59SJoseph Hwang 	 * https://cs.android.com/android/platform/superproject/+/
95749a6c59SJoseph Hwang 	 *         master:system/bt/gd/hci/controller.cc;l=477
96749a6c59SJoseph Hwang 	 */
97749a6c59SJoseph Hwang 	if (rp->bluetooth_quality_report_support) {
98749a6c59SJoseph Hwang 		hdev->aosp_quality_report = true;
99749a6c59SJoseph Hwang 		bt_dev_info(hdev, "AOSP quality report is supported");
100749a6c59SJoseph Hwang 	}
101749a6c59SJoseph Hwang 
102749a6c59SJoseph Hwang 	goto done;
103749a6c59SJoseph Hwang 
104749a6c59SJoseph Hwang length_error:
105749a6c59SJoseph Hwang 	bt_dev_err(hdev, "AOSP capabilities length %d too short", skb->len);
106749a6c59SJoseph Hwang 
107749a6c59SJoseph Hwang done:
108f67743f9SMarcel Holtmann 	kfree_skb(skb);
109f67743f9SMarcel Holtmann }
110f67743f9SMarcel Holtmann 
aosp_do_close(struct hci_dev * hdev)111f67743f9SMarcel Holtmann void aosp_do_close(struct hci_dev *hdev)
112f67743f9SMarcel Holtmann {
113f67743f9SMarcel Holtmann 	if (!hdev->aosp_capable)
114f67743f9SMarcel Holtmann 		return;
115f67743f9SMarcel Holtmann 
116f67743f9SMarcel Holtmann 	bt_dev_dbg(hdev, "Cleanup of AOSP extension");
117f67743f9SMarcel Holtmann }
118258f56d1SJoseph Hwang 
119258f56d1SJoseph Hwang /* BQR command */
120258f56d1SJoseph Hwang #define BQR_OPCODE			hci_opcode_pack(0x3f, 0x015e)
121258f56d1SJoseph Hwang 
122258f56d1SJoseph Hwang /* BQR report action */
123258f56d1SJoseph Hwang #define REPORT_ACTION_ADD		0x00
124258f56d1SJoseph Hwang #define REPORT_ACTION_DELETE		0x01
125258f56d1SJoseph Hwang #define REPORT_ACTION_CLEAR		0x02
126258f56d1SJoseph Hwang 
127258f56d1SJoseph Hwang /* BQR event masks */
128258f56d1SJoseph Hwang #define QUALITY_MONITORING		BIT(0)
129258f56d1SJoseph Hwang #define APPRAOCHING_LSTO		BIT(1)
130258f56d1SJoseph Hwang #define A2DP_AUDIO_CHOPPY		BIT(2)
131258f56d1SJoseph Hwang #define SCO_VOICE_CHOPPY		BIT(3)
132258f56d1SJoseph Hwang 
133258f56d1SJoseph Hwang #define DEFAULT_BQR_EVENT_MASK	(QUALITY_MONITORING | APPRAOCHING_LSTO | \
134258f56d1SJoseph Hwang 				 A2DP_AUDIO_CHOPPY | SCO_VOICE_CHOPPY)
135258f56d1SJoseph Hwang 
136258f56d1SJoseph Hwang /* Reporting at milliseconds so as not to stress the controller too much.
137258f56d1SJoseph Hwang  * Range: 0 ~ 65535 ms
138258f56d1SJoseph Hwang  */
139258f56d1SJoseph Hwang #define DEFALUT_REPORT_INTERVAL_MS	5000
140258f56d1SJoseph Hwang 
141258f56d1SJoseph Hwang struct aosp_bqr_cp {
142258f56d1SJoseph Hwang 	__u8	report_action;
143258f56d1SJoseph Hwang 	__u32	event_mask;
144258f56d1SJoseph Hwang 	__u16	min_report_interval;
145258f56d1SJoseph Hwang } __packed;
146258f56d1SJoseph Hwang 
enable_quality_report(struct hci_dev * hdev)147258f56d1SJoseph Hwang static int enable_quality_report(struct hci_dev *hdev)
148258f56d1SJoseph Hwang {
149258f56d1SJoseph Hwang 	struct sk_buff *skb;
150258f56d1SJoseph Hwang 	struct aosp_bqr_cp cp;
151258f56d1SJoseph Hwang 
152258f56d1SJoseph Hwang 	cp.report_action = REPORT_ACTION_ADD;
153258f56d1SJoseph Hwang 	cp.event_mask = DEFAULT_BQR_EVENT_MASK;
154258f56d1SJoseph Hwang 	cp.min_report_interval = DEFALUT_REPORT_INTERVAL_MS;
155258f56d1SJoseph Hwang 
156258f56d1SJoseph Hwang 	skb = __hci_cmd_sync(hdev, BQR_OPCODE, sizeof(cp), &cp,
157258f56d1SJoseph Hwang 			     HCI_CMD_TIMEOUT);
158*ce78e557SSoenke Huster 	if (IS_ERR_OR_NULL(skb)) {
159*ce78e557SSoenke Huster 		if (!skb)
160*ce78e557SSoenke Huster 			skb = ERR_PTR(-EIO);
161*ce78e557SSoenke Huster 
162258f56d1SJoseph Hwang 		bt_dev_err(hdev, "Enabling Android BQR failed (%ld)",
163258f56d1SJoseph Hwang 			   PTR_ERR(skb));
164258f56d1SJoseph Hwang 		return PTR_ERR(skb);
165258f56d1SJoseph Hwang 	}
166258f56d1SJoseph Hwang 
167258f56d1SJoseph Hwang 	kfree_skb(skb);
168258f56d1SJoseph Hwang 	return 0;
169258f56d1SJoseph Hwang }
170258f56d1SJoseph Hwang 
disable_quality_report(struct hci_dev * hdev)171258f56d1SJoseph Hwang static int disable_quality_report(struct hci_dev *hdev)
172258f56d1SJoseph Hwang {
173258f56d1SJoseph Hwang 	struct sk_buff *skb;
174258f56d1SJoseph Hwang 	struct aosp_bqr_cp cp = { 0 };
175258f56d1SJoseph Hwang 
176258f56d1SJoseph Hwang 	cp.report_action = REPORT_ACTION_CLEAR;
177258f56d1SJoseph Hwang 
178258f56d1SJoseph Hwang 	skb = __hci_cmd_sync(hdev, BQR_OPCODE, sizeof(cp), &cp,
179258f56d1SJoseph Hwang 			     HCI_CMD_TIMEOUT);
180*ce78e557SSoenke Huster 	if (IS_ERR_OR_NULL(skb)) {
181*ce78e557SSoenke Huster 		if (!skb)
182*ce78e557SSoenke Huster 			skb = ERR_PTR(-EIO);
183*ce78e557SSoenke Huster 
184258f56d1SJoseph Hwang 		bt_dev_err(hdev, "Disabling Android BQR failed (%ld)",
185258f56d1SJoseph Hwang 			   PTR_ERR(skb));
186258f56d1SJoseph Hwang 		return PTR_ERR(skb);
187258f56d1SJoseph Hwang 	}
188258f56d1SJoseph Hwang 
189258f56d1SJoseph Hwang 	kfree_skb(skb);
190258f56d1SJoseph Hwang 	return 0;
191258f56d1SJoseph Hwang }
192258f56d1SJoseph Hwang 
aosp_has_quality_report(struct hci_dev * hdev)193258f56d1SJoseph Hwang bool aosp_has_quality_report(struct hci_dev *hdev)
194258f56d1SJoseph Hwang {
195258f56d1SJoseph Hwang 	return hdev->aosp_quality_report;
196258f56d1SJoseph Hwang }
197258f56d1SJoseph Hwang 
aosp_set_quality_report(struct hci_dev * hdev,bool enable)198258f56d1SJoseph Hwang int aosp_set_quality_report(struct hci_dev *hdev, bool enable)
199258f56d1SJoseph Hwang {
200258f56d1SJoseph Hwang 	if (!aosp_has_quality_report(hdev))
201258f56d1SJoseph Hwang 		return -EOPNOTSUPP;
202258f56d1SJoseph Hwang 
203258f56d1SJoseph Hwang 	bt_dev_dbg(hdev, "quality report enable %d", enable);
204258f56d1SJoseph Hwang 
205258f56d1SJoseph Hwang 	/* Enable or disable the quality report feature. */
206258f56d1SJoseph Hwang 	if (enable)
207258f56d1SJoseph Hwang 		return enable_quality_report(hdev);
208258f56d1SJoseph Hwang 	else
209258f56d1SJoseph Hwang 		return disable_quality_report(hdev);
210258f56d1SJoseph Hwang }
211