device.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Device management routines
  4. * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
  5. */
  6. #include <linux/slab.h>
  7. #include <linux/time.h>
  8. #include <linux/export.h>
  9. #include <linux/errno.h>
  10. #include <sound/core.h>
  11. /**
  12. * snd_device_new - create an ALSA device component
  13. * @card: the card instance
  14. * @type: the device type, SNDRV_DEV_XXX
  15. * @device_data: the data pointer of this device
  16. * @ops: the operator table
  17. *
  18. * Creates a new device component for the given data pointer.
  19. * The device will be assigned to the card and managed together
  20. * by the card.
  21. *
  22. * The data pointer plays a role as the identifier, too, so the
  23. * pointer address must be unique and unchanged.
  24. *
  25. * Return: Zero if successful, or a negative error code on failure.
  26. */
  27. int snd_device_new(struct snd_card *card, enum snd_device_type type,
  28. void *device_data, const struct snd_device_ops *ops)
  29. {
  30. struct snd_device *dev;
  31. struct list_head *p;
  32. if (snd_BUG_ON(!card || !device_data || !ops))
  33. return -ENXIO;
  34. dev = kzalloc(sizeof(*dev), GFP_KERNEL);
  35. if (!dev)
  36. return -ENOMEM;
  37. INIT_LIST_HEAD(&dev->list);
  38. dev->card = card;
  39. dev->type = type;
  40. dev->state = SNDRV_DEV_BUILD;
  41. dev->device_data = device_data;
  42. dev->ops = ops;
  43. /* insert the entry in an incrementally sorted list */
  44. list_for_each_prev(p, &card->devices) {
  45. struct snd_device *pdev = list_entry(p, struct snd_device, list);
  46. if ((unsigned int)pdev->type <= (unsigned int)type)
  47. break;
  48. }
  49. list_add(&dev->list, p);
  50. return 0;
  51. }
  52. EXPORT_SYMBOL(snd_device_new);
  53. static void __snd_device_disconnect(struct snd_device *dev)
  54. {
  55. if (dev->state == SNDRV_DEV_REGISTERED) {
  56. if (dev->ops->dev_disconnect &&
  57. dev->ops->dev_disconnect(dev))
  58. dev_err(dev->card->dev, "device disconnect failure\n");
  59. dev->state = SNDRV_DEV_DISCONNECTED;
  60. }
  61. }
  62. static void __snd_device_free(struct snd_device *dev)
  63. {
  64. /* unlink */
  65. list_del(&dev->list);
  66. __snd_device_disconnect(dev);
  67. if (dev->ops->dev_free) {
  68. if (dev->ops->dev_free(dev))
  69. dev_err(dev->card->dev, "device free failure\n");
  70. }
  71. kfree(dev);
  72. }
  73. static struct snd_device *look_for_dev(struct snd_card *card, void *device_data)
  74. {
  75. struct snd_device *dev;
  76. list_for_each_entry(dev, &card->devices, list)
  77. if (dev->device_data == device_data)
  78. return dev;
  79. return NULL;
  80. }
  81. /**
  82. * snd_device_disconnect - disconnect the device
  83. * @card: the card instance
  84. * @device_data: the data pointer to disconnect
  85. *
  86. * Turns the device into the disconnection state, invoking
  87. * dev_disconnect callback, if the device was already registered.
  88. *
  89. * Usually called from snd_card_disconnect().
  90. *
  91. * Return: Zero if successful, or a negative error code on failure or if the
  92. * device not found.
  93. */
  94. void snd_device_disconnect(struct snd_card *card, void *device_data)
  95. {
  96. struct snd_device *dev;
  97. if (snd_BUG_ON(!card || !device_data))
  98. return;
  99. dev = look_for_dev(card, device_data);
  100. if (dev)
  101. __snd_device_disconnect(dev);
  102. else
  103. dev_dbg(card->dev, "device disconnect %p (from %pS), not found\n",
  104. device_data, __builtin_return_address(0));
  105. }
  106. EXPORT_SYMBOL_GPL(snd_device_disconnect);
  107. /**
  108. * snd_device_free - release the device from the card
  109. * @card: the card instance
  110. * @device_data: the data pointer to release
  111. *
  112. * Removes the device from the list on the card and invokes the
  113. * callbacks, dev_disconnect and dev_free, corresponding to the state.
  114. * Then release the device.
  115. */
  116. void snd_device_free(struct snd_card *card, void *device_data)
  117. {
  118. struct snd_device *dev;
  119. if (snd_BUG_ON(!card || !device_data))
  120. return;
  121. dev = look_for_dev(card, device_data);
  122. if (dev)
  123. __snd_device_free(dev);
  124. else
  125. dev_dbg(card->dev, "device free %p (from %pS), not found\n",
  126. device_data, __builtin_return_address(0));
  127. }
  128. EXPORT_SYMBOL(snd_device_free);
  129. static int __snd_device_register(struct snd_device *dev)
  130. {
  131. if (dev->state == SNDRV_DEV_BUILD) {
  132. if (dev->ops->dev_register) {
  133. int err = dev->ops->dev_register(dev);
  134. if (err < 0)
  135. return err;
  136. }
  137. dev->state = SNDRV_DEV_REGISTERED;
  138. }
  139. return 0;
  140. }
  141. /**
  142. * snd_device_register - register the device
  143. * @card: the card instance
  144. * @device_data: the data pointer to register
  145. *
  146. * Registers the device which was already created via
  147. * snd_device_new(). Usually this is called from snd_card_register(),
  148. * but it can be called later if any new devices are created after
  149. * invocation of snd_card_register().
  150. *
  151. * Return: Zero if successful, or a negative error code on failure or if the
  152. * device not found.
  153. */
  154. int snd_device_register(struct snd_card *card, void *device_data)
  155. {
  156. struct snd_device *dev;
  157. if (snd_BUG_ON(!card || !device_data))
  158. return -ENXIO;
  159. dev = look_for_dev(card, device_data);
  160. if (dev)
  161. return __snd_device_register(dev);
  162. snd_BUG();
  163. return -ENXIO;
  164. }
  165. EXPORT_SYMBOL(snd_device_register);
  166. /*
  167. * register all the devices on the card.
  168. * called from init.c
  169. */
  170. int snd_device_register_all(struct snd_card *card)
  171. {
  172. struct snd_device *dev;
  173. int err;
  174. if (snd_BUG_ON(!card))
  175. return -ENXIO;
  176. list_for_each_entry(dev, &card->devices, list) {
  177. err = __snd_device_register(dev);
  178. if (err < 0)
  179. return err;
  180. }
  181. return 0;
  182. }
  183. /*
  184. * disconnect all the devices on the card.
  185. * called from init.c
  186. */
  187. void snd_device_disconnect_all(struct snd_card *card)
  188. {
  189. struct snd_device *dev;
  190. if (snd_BUG_ON(!card))
  191. return;
  192. list_for_each_entry_reverse(dev, &card->devices, list)
  193. __snd_device_disconnect(dev);
  194. }
  195. /*
  196. * release all the devices on the card.
  197. * called from init.c
  198. */
  199. void snd_device_free_all(struct snd_card *card)
  200. {
  201. struct snd_device *dev, *next;
  202. if (snd_BUG_ON(!card))
  203. return;
  204. list_for_each_entry_safe_reverse(dev, next, &card->devices, list) {
  205. /* exception: free ctl and lowlevel stuff later */
  206. if (dev->type == SNDRV_DEV_CONTROL ||
  207. dev->type == SNDRV_DEV_LOWLEVEL)
  208. continue;
  209. __snd_device_free(dev);
  210. }
  211. /* free all */
  212. list_for_each_entry_safe_reverse(dev, next, &card->devices, list)
  213. __snd_device_free(dev);
  214. }
  215. /**
  216. * snd_device_get_state - Get the current state of the given device
  217. * @card: the card instance
  218. * @device_data: the data pointer to release
  219. *
  220. * Returns the current state of the given device object. For the valid
  221. * device, either @SNDRV_DEV_BUILD, @SNDRV_DEV_REGISTERED or
  222. * @SNDRV_DEV_DISCONNECTED is returned.
  223. * Or for a non-existing device, -1 is returned as an error.
  224. */
  225. int snd_device_get_state(struct snd_card *card, void *device_data)
  226. {
  227. struct snd_device *dev;
  228. dev = look_for_dev(card, device_data);
  229. if (dev)
  230. return dev->state;
  231. return -1;
  232. }
  233. EXPORT_SYMBOL_GPL(snd_device_get_state);