toshiba_bluetooth.c 7.0 KB

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