toshiba_bluetooth.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  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 int 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. .owner = THIS_MODULE,
  53. .drv.pm = &toshiba_bt_pm,
  54. };
  55. static int toshiba_bluetooth_present(acpi_handle handle)
  56. {
  57. acpi_status result;
  58. u64 bt_present;
  59. /*
  60. * Some Toshiba laptops may have a fake TOS6205 device in
  61. * their ACPI BIOS, so query the _STA method to see if there
  62. * is really anything there.
  63. */
  64. result = acpi_evaluate_integer(handle, "_STA", NULL, &bt_present);
  65. if (ACPI_FAILURE(result)) {
  66. pr_err("ACPI call to query Bluetooth presence failed\n");
  67. return -ENXIO;
  68. }
  69. if (!bt_present) {
  70. pr_info("Bluetooth device not present\n");
  71. return -ENODEV;
  72. }
  73. return 0;
  74. }
  75. static int toshiba_bluetooth_status(acpi_handle handle)
  76. {
  77. acpi_status result;
  78. u64 status;
  79. result = acpi_evaluate_integer(handle, "BTST", NULL, &status);
  80. if (ACPI_FAILURE(result)) {
  81. pr_err("Could not get Bluetooth device status\n");
  82. return -ENXIO;
  83. }
  84. return status;
  85. }
  86. static int toshiba_bluetooth_enable(acpi_handle handle)
  87. {
  88. acpi_status result;
  89. result = acpi_evaluate_object(handle, "AUSB", NULL, NULL);
  90. if (ACPI_FAILURE(result)) {
  91. pr_err("Could not attach USB Bluetooth device\n");
  92. return -ENXIO;
  93. }
  94. result = acpi_evaluate_object(handle, "BTPO", NULL, NULL);
  95. if (ACPI_FAILURE(result)) {
  96. pr_err("Could not power ON Bluetooth device\n");
  97. return -ENXIO;
  98. }
  99. return 0;
  100. }
  101. static int toshiba_bluetooth_disable(acpi_handle handle)
  102. {
  103. acpi_status result;
  104. result = acpi_evaluate_object(handle, "BTPF", NULL, NULL);
  105. if (ACPI_FAILURE(result)) {
  106. pr_err("Could not power OFF Bluetooth device\n");
  107. return -ENXIO;
  108. }
  109. result = acpi_evaluate_object(handle, "DUSB", NULL, NULL);
  110. if (ACPI_FAILURE(result)) {
  111. pr_err("Could not detach USB Bluetooth device\n");
  112. return -ENXIO;
  113. }
  114. return 0;
  115. }
  116. /* Helper function */
  117. static int toshiba_bluetooth_sync_status(struct toshiba_bluetooth_dev *bt_dev)
  118. {
  119. int status;
  120. status = toshiba_bluetooth_status(bt_dev->acpi_dev->handle);
  121. if (status < 0) {
  122. pr_err("Could not sync bluetooth device status\n");
  123. return status;
  124. }
  125. bt_dev->killswitch = (status & BT_KILLSWITCH_MASK) ? true : false;
  126. bt_dev->plugged = (status & BT_PLUGGED_MASK) ? true : false;
  127. bt_dev->powered = (status & BT_POWER_MASK) ? true : false;
  128. pr_debug("Bluetooth status %d killswitch %d plugged %d powered %d\n",
  129. status, bt_dev->killswitch, bt_dev->plugged, bt_dev->powered);
  130. return 0;
  131. }
  132. /* RFKill handlers */
  133. static int bt_rfkill_set_block(void *data, bool blocked)
  134. {
  135. struct toshiba_bluetooth_dev *bt_dev = data;
  136. int ret;
  137. ret = toshiba_bluetooth_sync_status(bt_dev);
  138. if (ret)
  139. return ret;
  140. if (!bt_dev->killswitch)
  141. return 0;
  142. if (blocked)
  143. ret = toshiba_bluetooth_disable(bt_dev->acpi_dev->handle);
  144. else
  145. ret = toshiba_bluetooth_enable(bt_dev->acpi_dev->handle);
  146. return ret;
  147. }
  148. static void bt_rfkill_poll(struct rfkill *rfkill, void *data)
  149. {
  150. struct toshiba_bluetooth_dev *bt_dev = data;
  151. if (toshiba_bluetooth_sync_status(bt_dev))
  152. return;
  153. /*
  154. * Note the Toshiba Bluetooth RFKill switch seems to be a strange
  155. * fish. It only provides a BT event when the switch is flipped to
  156. * the 'on' position. When flipping it to 'off', the USB device is
  157. * simply pulled away underneath us, without any BT event being
  158. * delivered.
  159. */
  160. rfkill_set_hw_state(bt_dev->rfk, !bt_dev->killswitch);
  161. }
  162. static const struct rfkill_ops rfk_ops = {
  163. .set_block = bt_rfkill_set_block,
  164. .poll = bt_rfkill_poll,
  165. };
  166. /* ACPI driver functions */
  167. static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event)
  168. {
  169. struct toshiba_bluetooth_dev *bt_dev = acpi_driver_data(device);
  170. if (toshiba_bluetooth_sync_status(bt_dev))
  171. return;
  172. rfkill_set_hw_state(bt_dev->rfk, !bt_dev->killswitch);
  173. }
  174. #ifdef CONFIG_PM_SLEEP
  175. static int toshiba_bt_resume(struct device *dev)
  176. {
  177. struct toshiba_bluetooth_dev *bt_dev;
  178. int ret;
  179. bt_dev = acpi_driver_data(to_acpi_device(dev));
  180. ret = toshiba_bluetooth_sync_status(bt_dev);
  181. if (ret)
  182. return ret;
  183. rfkill_set_hw_state(bt_dev->rfk, !bt_dev->killswitch);
  184. return 0;
  185. }
  186. #endif
  187. static int toshiba_bt_rfkill_add(struct acpi_device *device)
  188. {
  189. struct toshiba_bluetooth_dev *bt_dev;
  190. int result;
  191. result = toshiba_bluetooth_present(device->handle);
  192. if (result)
  193. return result;
  194. pr_info("Toshiba ACPI Bluetooth device driver\n");
  195. bt_dev = kzalloc(sizeof(*bt_dev), GFP_KERNEL);
  196. if (!bt_dev)
  197. return -ENOMEM;
  198. bt_dev->acpi_dev = device;
  199. device->driver_data = bt_dev;
  200. dev_set_drvdata(&device->dev, bt_dev);
  201. result = toshiba_bluetooth_sync_status(bt_dev);
  202. if (result) {
  203. kfree(bt_dev);
  204. return result;
  205. }
  206. bt_dev->rfk = rfkill_alloc("Toshiba Bluetooth",
  207. &device->dev,
  208. RFKILL_TYPE_BLUETOOTH,
  209. &rfk_ops,
  210. bt_dev);
  211. if (!bt_dev->rfk) {
  212. pr_err("Unable to allocate rfkill device\n");
  213. kfree(bt_dev);
  214. return -ENOMEM;
  215. }
  216. rfkill_set_hw_state(bt_dev->rfk, !bt_dev->killswitch);
  217. result = rfkill_register(bt_dev->rfk);
  218. if (result) {
  219. pr_err("Unable to register rfkill device\n");
  220. rfkill_destroy(bt_dev->rfk);
  221. kfree(bt_dev);
  222. }
  223. return result;
  224. }
  225. static int toshiba_bt_rfkill_remove(struct acpi_device *device)
  226. {
  227. struct toshiba_bluetooth_dev *bt_dev = acpi_driver_data(device);
  228. /* clean up */
  229. if (bt_dev->rfk) {
  230. rfkill_unregister(bt_dev->rfk);
  231. rfkill_destroy(bt_dev->rfk);
  232. }
  233. kfree(bt_dev);
  234. return toshiba_bluetooth_disable(device->handle);
  235. }
  236. module_acpi_driver(toshiba_bt_rfkill_driver);