Skip to content

Commit b8f5482

Browse files
Vudentzholtmann
authored andcommitted
Bluetooth: vhci: Add support for setting msft_opcode and aosp_capable
This adds a debugfs entries to set msft_opcode and aosp_capable enabling vhci to emulate controllers with MSFT/AOSP extension support. Signed-off-by: Luiz Augusto von Dentz <[email protected]> Signed-off-by: Marcel Holtmann <[email protected]>
1 parent 60c6a63 commit b8f5482

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

drivers/bluetooth/hci_vhci.c

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ struct vhci_data {
4242

4343
bool suspended;
4444
bool wakeup;
45+
__u16 msft_opcode;
46+
bool aosp_capable;
4547
};
4648

4749
static int vhci_open_dev(struct hci_dev *hdev)
@@ -194,6 +196,88 @@ static const struct file_operations force_wakeup_fops = {
194196
.llseek = default_llseek,
195197
};
196198

199+
static int msft_opcode_set(void *data, u64 val)
200+
{
201+
struct vhci_data *vhci = data;
202+
203+
if (val > 0xffff || (val & 0xffff >> 10) != 0x3f)
204+
return -EINVAL;
205+
206+
if (vhci->msft_opcode)
207+
return -EALREADY;
208+
209+
vhci->msft_opcode = val;
210+
211+
return 0;
212+
}
213+
214+
static int msft_opcode_get(void *data, u64 *val)
215+
{
216+
struct vhci_data *vhci = data;
217+
218+
*val = vhci->msft_opcode;
219+
220+
return 0;
221+
}
222+
223+
DEFINE_DEBUGFS_ATTRIBUTE(msft_opcode_fops, msft_opcode_get, msft_opcode_set,
224+
"%llu\n");
225+
226+
static ssize_t aosp_capable_read(struct file *file, char __user *user_buf,
227+
size_t count, loff_t *ppos)
228+
{
229+
struct vhci_data *vhci = file->private_data;
230+
char buf[3];
231+
232+
buf[0] = vhci->aosp_capable ? 'Y' : 'N';
233+
buf[1] = '\n';
234+
buf[2] = '\0';
235+
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
236+
}
237+
238+
static ssize_t aosp_capable_write(struct file *file,
239+
const char __user *user_buf, size_t count,
240+
loff_t *ppos)
241+
{
242+
struct vhci_data *vhci = file->private_data;
243+
bool enable;
244+
int err;
245+
246+
err = kstrtobool_from_user(user_buf, count, &enable);
247+
if (err)
248+
return err;
249+
250+
if (!enable)
251+
return -EINVAL;
252+
253+
if (vhci->aosp_capable)
254+
return -EALREADY;
255+
256+
vhci->aosp_capable = enable;
257+
258+
return count;
259+
}
260+
261+
static const struct file_operations aosp_capable_fops = {
262+
.open = simple_open,
263+
.read = aosp_capable_read,
264+
.write = aosp_capable_write,
265+
.llseek = default_llseek,
266+
};
267+
268+
static int vhci_setup(struct hci_dev *hdev)
269+
{
270+
struct vhci_data *vhci = hci_get_drvdata(hdev);
271+
272+
if (vhci->msft_opcode)
273+
hci_set_msft_opcode(hdev, vhci->msft_opcode);
274+
275+
if (vhci->aosp_capable)
276+
hci_set_aosp_capable(hdev);
277+
278+
return 0;
279+
}
280+
197281
static int __vhci_create_device(struct vhci_data *data, __u8 opcode)
198282
{
199283
struct hci_dev *hdev;
@@ -236,6 +320,8 @@ static int __vhci_create_device(struct vhci_data *data, __u8 opcode)
236320
hdev->get_data_path_id = vhci_get_data_path_id;
237321
hdev->get_codec_config_data = vhci_get_codec_config_data;
238322
hdev->wakeup = vhci_wakeup;
323+
hdev->setup = vhci_setup;
324+
set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
239325

240326
/* bit 6 is for external configuration */
241327
if (opcode & 0x40)
@@ -259,6 +345,14 @@ static int __vhci_create_device(struct vhci_data *data, __u8 opcode)
259345
debugfs_create_file("force_wakeup", 0644, hdev->debugfs, data,
260346
&force_wakeup_fops);
261347

348+
if (IS_ENABLED(CONFIG_BT_MSFTEXT))
349+
debugfs_create_file("msft_opcode", 0644, hdev->debugfs, data,
350+
&msft_opcode_fops);
351+
352+
if (IS_ENABLED(CONFIG_BT_AOSPEXT))
353+
debugfs_create_file("aosp_capable", 0644, hdev->debugfs, data,
354+
&aosp_capable_fops);
355+
262356
hci_skb_pkt_type(skb) = HCI_VENDOR_PKT;
263357

264358
skb_put_u8(skb, 0xff);

0 commit comments

Comments
 (0)