otg_id.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * Copyright (C) 2011 Google, Inc.
  3. *
  4. * Author:
  5. * Colin Cross <ccross@android.com>
  6. *
  7. * This software is licensed under the terms of the GNU General Public
  8. * License version 2, as published by the Free Software Foundation, and
  9. * may be copied, distributed, and modified under those terms.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. */
  17. #include <linux/kernel.h>
  18. #include <linux/mutex.h>
  19. #include <linux/notifier.h>
  20. #include <linux/usb/otg_id.h>
  21. static DEFINE_MUTEX(otg_id_lock);
  22. static struct plist_head otg_id_plist =
  23. PLIST_HEAD_INIT(otg_id_plist);
  24. static struct otg_id_notifier_block *otg_id_active;
  25. static bool otg_id_cancelling;
  26. static bool otg_id_inited;
  27. static int otg_id_suspended;
  28. static bool otg_id_pending;
  29. static void otg_id_cancel(void)
  30. {
  31. if (otg_id_active) {
  32. otg_id_cancelling = true;
  33. mutex_unlock(&otg_id_lock);
  34. otg_id_active->cancel(otg_id_active);
  35. mutex_lock(&otg_id_lock);
  36. otg_id_cancelling = false;
  37. }
  38. }
  39. static void __otg_id_notify(void)
  40. {
  41. int ret;
  42. struct otg_id_notifier_block *otg_id_nb;
  43. bool proxy_wait = false;
  44. if (plist_head_empty(&otg_id_plist))
  45. return;
  46. plist_for_each_entry(otg_id_nb, &otg_id_plist, p) {
  47. if (proxy_wait) {
  48. if (otg_id_nb->proxy_wait)
  49. ret = otg_id_nb->proxy_wait(otg_id_nb);
  50. } else {
  51. ret = otg_id_nb->detect(otg_id_nb);
  52. }
  53. if (ret == OTG_ID_HANDLED) {
  54. otg_id_active = otg_id_nb;
  55. return;
  56. }
  57. if (ret == OTG_ID_PROXY_WAIT)
  58. proxy_wait = true;
  59. }
  60. WARN(1, "otg id event not handled");
  61. otg_id_active = NULL;
  62. }
  63. int otg_id_init(void)
  64. {
  65. mutex_lock(&otg_id_lock);
  66. otg_id_inited = true;
  67. __otg_id_notify();
  68. mutex_unlock(&otg_id_lock);
  69. return 0;
  70. }
  71. late_initcall(otg_id_init);
  72. /**
  73. * otg_id_register_notifier
  74. * @otg_id_nb: notifier block containing priority and callback function
  75. *
  76. * Register a notifier that will be called on any USB cable state change.
  77. * The priority determines the order the callback will be called in, a higher
  78. * number will be called first. A callback function needs to determine the
  79. * type of USB cable that is connected. If it can determine the type, it
  80. * should notify the appropriate drivers (for example, call an otg notifier
  81. * with USB_EVENT_VBUS), and return OTG_ID_HANDLED. Once a callback has
  82. * returned OTG_ID_HANDLED, it is responsible for calling otg_id_notify() when
  83. * the detected USB cable is disconnected.
  84. */
  85. int otg_id_register_notifier(struct otg_id_notifier_block *otg_id_nb)
  86. {
  87. plist_node_init(&otg_id_nb->p, otg_id_nb->priority);
  88. mutex_lock(&otg_id_lock);
  89. plist_add(&otg_id_nb->p, &otg_id_plist);
  90. if (otg_id_inited) {
  91. otg_id_cancel();
  92. __otg_id_notify();
  93. }
  94. mutex_unlock(&otg_id_lock);
  95. return 0;
  96. }
  97. void otg_id_unregister_notifier(struct otg_id_notifier_block *otg_id_nb)
  98. {
  99. mutex_lock(&otg_id_lock);
  100. plist_del(&otg_id_nb->p, &otg_id_plist);
  101. if (otg_id_inited && (otg_id_active == otg_id_nb)) {
  102. otg_id_cancel();
  103. __otg_id_notify();
  104. }
  105. mutex_unlock(&otg_id_lock);
  106. }
  107. /**
  108. * otg_id_notify
  109. *
  110. * Notify listeners on any USB cable state change.
  111. *
  112. * A driver may only call otg_id_notify if it returned OTG_ID_HANDLED the last
  113. * time it's notifier was called, and it's cancel function has not been called.
  114. */
  115. void otg_id_notify(void)
  116. {
  117. mutex_lock(&otg_id_lock);
  118. if (otg_id_cancelling)
  119. goto out;
  120. if (otg_id_suspended != 0) {
  121. otg_id_pending = true;
  122. goto out;
  123. }
  124. __otg_id_notify();
  125. out:
  126. mutex_unlock(&otg_id_lock);
  127. }
  128. /**
  129. * otg_id_suspend
  130. *
  131. * Mark the otg_id subsystem as going into suspend. From here on out,
  132. * any notifications will be deferred until the last otg_id client resumes.
  133. * If there is a pending notification when calling this function, it will
  134. * return a negative errno and expects that the caller will abort suspend.
  135. * Returs 0 on success.
  136. */
  137. int otg_id_suspend(void)
  138. {
  139. int ret = 0;
  140. mutex_lock(&otg_id_lock);
  141. /*
  142. * if there's a pending notification, tell the caller to abort suspend
  143. */
  144. if (otg_id_suspended != 0 && otg_id_pending) {
  145. pr_info("otg_id: pending notification, should abort suspend\n");
  146. ret = -EBUSY;
  147. goto out;
  148. }
  149. otg_id_suspended++;
  150. out:
  151. mutex_unlock(&otg_id_lock);
  152. return ret;
  153. }
  154. /**
  155. * otg_id_resume
  156. *
  157. * Inform the otg_id subsystem that a client is resuming. If this is the
  158. * last client to be resumed and there's a pending notification,
  159. * otg_id_notify() is called.
  160. */
  161. void otg_id_resume(void)
  162. {
  163. mutex_lock(&otg_id_lock);
  164. if (WARN(!otg_id_suspended, "unbalanced otg_id_resume\n"))
  165. goto out;
  166. if (--otg_id_suspended == 0) {
  167. if (otg_id_pending) {
  168. pr_info("otg_id: had pending notification\n");
  169. otg_id_pending = false;
  170. __otg_id_notify();
  171. }
  172. }
  173. out:
  174. mutex_unlock(&otg_id_lock);
  175. }