toshiba_bluetooth.c 6.9 KB

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