toshiba_bluetooth.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Toshiba Bluetooth Enable Driver
  4. *
  5. * Copyright (C) 2009 Jes Sorensen <Jes.Sorensen@gmail.com>
  6. * Copyright (C) 2015 Azael Avalos <coproscefalo@gmail.com>
  7. *
  8. * Thanks to Matthew Garrett for background info on ACPI innards which
  9. * normal people aren't meant to understand :-)
  10. */
  11. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  12. #include <linux/kernel.h>
  13. #include <linux/module.h>
  14. #include <linux/init.h>
  15. #include <linux/types.h>
  16. #include <linux/acpi.h>
  17. #include <linux/rfkill.h>
  18. #define BT_KILLSWITCH_MASK 0x01
  19. #define BT_PLUGGED_MASK 0x40
  20. #define BT_POWER_MASK 0x80
  21. MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@gmail.com>");
  22. MODULE_DESCRIPTION("Toshiba Laptop ACPI Bluetooth Enable Driver");
  23. MODULE_LICENSE("GPL");
  24. struct toshiba_bluetooth_dev {
  25. struct acpi_device *acpi_dev;
  26. struct rfkill *rfk;
  27. bool killswitch;
  28. bool plugged;
  29. bool powered;
  30. };
  31. static int toshiba_bt_rfkill_add(struct acpi_device *device);
  32. static void toshiba_bt_rfkill_remove(struct acpi_device *device);
  33. static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event);
  34. static const struct acpi_device_id bt_device_ids[] = {
  35. { "TOS6205", 0},
  36. { "", 0},
  37. };
  38. MODULE_DEVICE_TABLE(acpi, bt_device_ids);
  39. #ifdef CONFIG_PM_SLEEP
  40. static int toshiba_bt_resume(struct device *dev);
  41. #endif
  42. static SIMPLE_DEV_PM_OPS(toshiba_bt_pm, NULL, toshiba_bt_resume);
  43. static struct acpi_driver toshiba_bt_rfkill_driver = {
  44. .name = "Toshiba BT",
  45. .class = "Toshiba",
  46. .ids = bt_device_ids,
  47. .ops = {
  48. .add = toshiba_bt_rfkill_add,
  49. .remove = toshiba_bt_rfkill_remove,
  50. .notify = toshiba_bt_rfkill_notify,
  51. },
  52. .drv.pm = &toshiba_bt_pm,
  53. };
  54. static int toshiba_bluetooth_present(acpi_handle handle)
  55. {
  56. acpi_status result;
  57. u64 bt_present;
  58. /*
  59. * Some Toshiba laptops may have a fake TOS6205 device in
  60. * their ACPI BIOS, so query the _STA method to see if there
  61. * is really anything there.
  62. */
  63. result = acpi_evaluate_integer(handle, "_STA", NULL, &bt_present);
  64. if (ACPI_FAILURE(result)) {
  65. pr_err("ACPI call to query Bluetooth presence failed\n");
  66. return -ENXIO;
  67. }
  68. if (!bt_present) {
  69. pr_info("Bluetooth device not present\n");
  70. return -ENODEV;
  71. }
  72. return 0;
  73. }
  74. static int toshiba_bluetooth_status(acpi_handle handle)
  75. {
  76. acpi_status result;
  77. u64 status;
  78. result = acpi_evaluate_integer(handle, "BTST", NULL, &status);
  79. if (ACPI_FAILURE(result)) {
  80. pr_err("Could not get Bluetooth device status\n");
  81. return -ENXIO;
  82. }
  83. return status;
  84. }
  85. static int toshiba_bluetooth_enable(acpi_handle handle)
  86. {
  87. acpi_status result;
  88. result = acpi_evaluate_object(handle, "AUSB", NULL, NULL);
  89. if (ACPI_FAILURE(result)) {
  90. pr_err("Could not attach USB Bluetooth device\n");
  91. return -ENXIO;
  92. }
  93. result = acpi_evaluate_object(handle, "BTPO", NULL, NULL);
  94. if (ACPI_FAILURE(result)) {
  95. pr_err("Could not power ON Bluetooth device\n");
  96. return -ENXIO;
  97. }
  98. return 0;
  99. }
  100. static int toshiba_bluetooth_disable(acpi_handle handle)
  101. {
  102. acpi_status result;
  103. result = acpi_evaluate_object(handle, "BTPF", NULL, NULL);
  104. if (ACPI_FAILURE(result)) {
  105. pr_err("Could not power OFF Bluetooth device\n");
  106. return -ENXIO;
  107. }
  108. result = acpi_evaluate_object(handle, "DUSB", NULL, NULL);
  109. if (ACPI_FAILURE(result)) {
  110. pr_err("Could not detach USB Bluetooth device\n");
  111. return -ENXIO;
  112. }
  113. return 0;
  114. }
  115. /* Helper function */
  116. static int toshiba_bluetooth_sync_status(struct toshiba_bluetooth_dev *bt_dev)
  117. {
  118. int status;
  119. status = toshiba_bluetooth_status(bt_dev->acpi_dev->handle);
  120. if (status < 0) {
  121. pr_err("Could not sync bluetooth device status\n");
  122. return status;
  123. }
  124. bt_dev->killswitch = (status & BT_KILLSWITCH_MASK) ? true : false;
  125. bt_dev->plugged = (status & BT_PLUGGED_MASK) ? true : false;
  126. bt_dev->powered = (status & BT_POWER_MASK) ? true : false;
  127. pr_debug("Bluetooth status %d killswitch %d plugged %d powered %d\n",
  128. status, bt_dev->killswitch, bt_dev->plugged, bt_dev->powered);
  129. return 0;
  130. }
  131. /* RFKill handlers */
  132. static int bt_rfkill_set_block(void *data, bool blocked)
  133. {
  134. struct toshiba_bluetooth_dev *bt_dev = data;
  135. int ret;
  136. ret = toshiba_bluetooth_sync_status(bt_dev);
  137. if (ret)
  138. return ret;
  139. if (!bt_dev->killswitch)
  140. return 0;
  141. if (blocked)
  142. ret = toshiba_bluetooth_disable(bt_dev->acpi_dev->handle);
  143. else
  144. ret = toshiba_bluetooth_enable(bt_dev->acpi_dev->handle);
  145. return ret;
  146. }
  147. static void bt_rfkill_poll(struct rfkill *rfkill, void *data)
  148. {
  149. struct toshiba_bluetooth_dev *bt_dev = data;
  150. if (toshiba_bluetooth_sync_status(bt_dev))
  151. return;
  152. /*
  153. * Note the Toshiba Bluetooth RFKill switch seems to be a strange
  154. * fish. It only provides a BT event when the switch is flipped to
  155. * the 'on' position. When flipping it to 'off', the USB device is
  156. * simply pulled away underneath us, without any BT event being
  157. * delivered.
  158. */
  159. rfkill_set_hw_state(bt_dev->rfk, !bt_dev->killswitch);
  160. }
  161. static const struct rfkill_ops rfk_ops = {
  162. .set_block = bt_rfkill_set_block,
  163. .poll = bt_rfkill_poll,
  164. };
  165. /* ACPI driver functions */
  166. static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event)
  167. {
  168. struct toshiba_bluetooth_dev *bt_dev = acpi_driver_data(device);
  169. if (toshiba_bluetooth_sync_status(bt_dev))
  170. return;
  171. rfkill_set_hw_state(bt_dev->rfk, !bt_dev->killswitch);
  172. }
  173. #ifdef CONFIG_PM_SLEEP
  174. static int toshiba_bt_resume(struct device *dev)
  175. {
  176. struct toshiba_bluetooth_dev *bt_dev;
  177. int ret;
  178. bt_dev = acpi_driver_data(to_acpi_device(dev));
  179. ret = toshiba_bluetooth_sync_status(bt_dev);
  180. if (ret)
  181. return ret;
  182. rfkill_set_hw_state(bt_dev->rfk, !bt_dev->killswitch);
  183. return 0;
  184. }
  185. #endif
  186. static int toshiba_bt_rfkill_add(struct acpi_device *device)
  187. {
  188. struct toshiba_bluetooth_dev *bt_dev;
  189. int result;
  190. result = toshiba_bluetooth_present(device->handle);
  191. if (result)
  192. return result;
  193. pr_info("Toshiba ACPI Bluetooth device driver\n");
  194. bt_dev = kzalloc_obj(*bt_dev);
  195. if (!bt_dev)
  196. return -ENOMEM;
  197. bt_dev->acpi_dev = device;
  198. device->driver_data = bt_dev;
  199. dev_set_drvdata(&device->dev, bt_dev);
  200. result = toshiba_bluetooth_sync_status(bt_dev);
  201. if (result) {
  202. kfree(bt_dev);
  203. return result;
  204. }
  205. bt_dev->rfk = rfkill_alloc("Toshiba Bluetooth",
  206. &device->dev,
  207. RFKILL_TYPE_BLUETOOTH,
  208. &rfk_ops,
  209. bt_dev);
  210. if (!bt_dev->rfk) {
  211. pr_err("Unable to allocate rfkill device\n");
  212. kfree(bt_dev);
  213. return -ENOMEM;
  214. }
  215. rfkill_set_hw_state(bt_dev->rfk, !bt_dev->killswitch);
  216. result = rfkill_register(bt_dev->rfk);
  217. if (result) {
  218. pr_err("Unable to register rfkill device\n");
  219. rfkill_destroy(bt_dev->rfk);
  220. kfree(bt_dev);
  221. }
  222. return result;
  223. }
  224. static void toshiba_bt_rfkill_remove(struct acpi_device *device)
  225. {
  226. struct toshiba_bluetooth_dev *bt_dev = acpi_driver_data(device);
  227. /* clean up */
  228. if (bt_dev->rfk) {
  229. rfkill_unregister(bt_dev->rfk);
  230. rfkill_destroy(bt_dev->rfk);
  231. }
  232. kfree(bt_dev);
  233. toshiba_bluetooth_disable(device->handle);
  234. }
  235. module_acpi_driver(toshiba_bt_rfkill_driver);