1 // SPDX-License-Identifier: GPL-2.0-only
3 * Toshiba Bluetooth Enable Driver
5 * Copyright (C) 2009 Jes Sorensen <Jes.Sorensen@gmail.com>
6 * Copyright (C) 2015 Azael Avalos <coproscefalo@gmail.com>
8 * Thanks to Matthew Garrett for background info on ACPI innards which
9 * normal people aren't meant to understand :-)
12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/types.h>
18 #include <linux/acpi.h>
19 #include <linux/rfkill.h>
21 #define BT_KILLSWITCH_MASK 0x01
22 #define BT_PLUGGED_MASK 0x40
23 #define BT_POWER_MASK 0x80
25 MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@gmail.com>");
26 MODULE_DESCRIPTION("Toshiba Laptop ACPI Bluetooth Enable Driver");
27 MODULE_LICENSE("GPL");
29 struct toshiba_bluetooth_dev
{
30 struct acpi_device
*acpi_dev
;
38 static int toshiba_bt_rfkill_add(struct acpi_device
*device
);
39 static int toshiba_bt_rfkill_remove(struct acpi_device
*device
);
40 static void toshiba_bt_rfkill_notify(struct acpi_device
*device
, u32 event
);
42 static const struct acpi_device_id bt_device_ids
[] = {
46 MODULE_DEVICE_TABLE(acpi
, bt_device_ids
);
48 #ifdef CONFIG_PM_SLEEP
49 static int toshiba_bt_resume(struct device
*dev
);
51 static SIMPLE_DEV_PM_OPS(toshiba_bt_pm
, NULL
, toshiba_bt_resume
);
53 static struct acpi_driver toshiba_bt_rfkill_driver
= {
58 .add
= toshiba_bt_rfkill_add
,
59 .remove
= toshiba_bt_rfkill_remove
,
60 .notify
= toshiba_bt_rfkill_notify
,
63 .drv
.pm
= &toshiba_bt_pm
,
66 static int toshiba_bluetooth_present(acpi_handle handle
)
72 * Some Toshiba laptops may have a fake TOS6205 device in
73 * their ACPI BIOS, so query the _STA method to see if there
74 * is really anything there.
76 result
= acpi_evaluate_integer(handle
, "_STA", NULL
, &bt_present
);
77 if (ACPI_FAILURE(result
)) {
78 pr_err("ACPI call to query Bluetooth presence failed\n");
83 pr_info("Bluetooth device not present\n");
90 static int toshiba_bluetooth_status(acpi_handle handle
)
95 result
= acpi_evaluate_integer(handle
, "BTST", NULL
, &status
);
96 if (ACPI_FAILURE(result
)) {
97 pr_err("Could not get Bluetooth device status\n");
104 static int toshiba_bluetooth_enable(acpi_handle handle
)
108 result
= acpi_evaluate_object(handle
, "AUSB", NULL
, NULL
);
109 if (ACPI_FAILURE(result
)) {
110 pr_err("Could not attach USB Bluetooth device\n");
114 result
= acpi_evaluate_object(handle
, "BTPO", NULL
, NULL
);
115 if (ACPI_FAILURE(result
)) {
116 pr_err("Could not power ON Bluetooth device\n");
123 static int toshiba_bluetooth_disable(acpi_handle handle
)
127 result
= acpi_evaluate_object(handle
, "BTPF", NULL
, NULL
);
128 if (ACPI_FAILURE(result
)) {
129 pr_err("Could not power OFF Bluetooth device\n");
133 result
= acpi_evaluate_object(handle
, "DUSB", NULL
, NULL
);
134 if (ACPI_FAILURE(result
)) {
135 pr_err("Could not detach USB Bluetooth device\n");
142 /* Helper function */
143 static int toshiba_bluetooth_sync_status(struct toshiba_bluetooth_dev
*bt_dev
)
147 status
= toshiba_bluetooth_status(bt_dev
->acpi_dev
->handle
);
149 pr_err("Could not sync bluetooth device status\n");
153 bt_dev
->killswitch
= (status
& BT_KILLSWITCH_MASK
) ? true : false;
154 bt_dev
->plugged
= (status
& BT_PLUGGED_MASK
) ? true : false;
155 bt_dev
->powered
= (status
& BT_POWER_MASK
) ? true : false;
157 pr_debug("Bluetooth status %d killswitch %d plugged %d powered %d\n",
158 status
, bt_dev
->killswitch
, bt_dev
->plugged
, bt_dev
->powered
);
163 /* RFKill handlers */
164 static int bt_rfkill_set_block(void *data
, bool blocked
)
166 struct toshiba_bluetooth_dev
*bt_dev
= data
;
169 ret
= toshiba_bluetooth_sync_status(bt_dev
);
173 if (!bt_dev
->killswitch
)
177 ret
= toshiba_bluetooth_disable(bt_dev
->acpi_dev
->handle
);
179 ret
= toshiba_bluetooth_enable(bt_dev
->acpi_dev
->handle
);
184 static void bt_rfkill_poll(struct rfkill
*rfkill
, void *data
)
186 struct toshiba_bluetooth_dev
*bt_dev
= data
;
188 if (toshiba_bluetooth_sync_status(bt_dev
))
192 * Note the Toshiba Bluetooth RFKill switch seems to be a strange
193 * fish. It only provides a BT event when the switch is flipped to
194 * the 'on' position. When flipping it to 'off', the USB device is
195 * simply pulled away underneath us, without any BT event being
198 rfkill_set_hw_state(bt_dev
->rfk
, !bt_dev
->killswitch
);
201 static const struct rfkill_ops rfk_ops
= {
202 .set_block
= bt_rfkill_set_block
,
203 .poll
= bt_rfkill_poll
,
206 /* ACPI driver functions */
207 static void toshiba_bt_rfkill_notify(struct acpi_device
*device
, u32 event
)
209 struct toshiba_bluetooth_dev
*bt_dev
= acpi_driver_data(device
);
211 if (toshiba_bluetooth_sync_status(bt_dev
))
214 rfkill_set_hw_state(bt_dev
->rfk
, !bt_dev
->killswitch
);
217 #ifdef CONFIG_PM_SLEEP
218 static int toshiba_bt_resume(struct device
*dev
)
220 struct toshiba_bluetooth_dev
*bt_dev
;
223 bt_dev
= acpi_driver_data(to_acpi_device(dev
));
225 ret
= toshiba_bluetooth_sync_status(bt_dev
);
229 rfkill_set_hw_state(bt_dev
->rfk
, !bt_dev
->killswitch
);
235 static int toshiba_bt_rfkill_add(struct acpi_device
*device
)
237 struct toshiba_bluetooth_dev
*bt_dev
;
240 result
= toshiba_bluetooth_present(device
->handle
);
244 pr_info("Toshiba ACPI Bluetooth device driver\n");
246 bt_dev
= kzalloc(sizeof(*bt_dev
), GFP_KERNEL
);
249 bt_dev
->acpi_dev
= device
;
250 device
->driver_data
= bt_dev
;
251 dev_set_drvdata(&device
->dev
, bt_dev
);
253 result
= toshiba_bluetooth_sync_status(bt_dev
);
259 bt_dev
->rfk
= rfkill_alloc("Toshiba Bluetooth",
261 RFKILL_TYPE_BLUETOOTH
,
265 pr_err("Unable to allocate rfkill device\n");
270 rfkill_set_hw_state(bt_dev
->rfk
, !bt_dev
->killswitch
);
272 result
= rfkill_register(bt_dev
->rfk
);
274 pr_err("Unable to register rfkill device\n");
275 rfkill_destroy(bt_dev
->rfk
);
282 static int toshiba_bt_rfkill_remove(struct acpi_device
*device
)
284 struct toshiba_bluetooth_dev
*bt_dev
= acpi_driver_data(device
);
288 rfkill_unregister(bt_dev
->rfk
);
289 rfkill_destroy(bt_dev
->rfk
);
294 return toshiba_bluetooth_disable(device
->handle
);
297 module_acpi_driver(toshiba_bt_rfkill_driver
);