hotplug.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /* -*- Mode: C; indent-tabs-mode:nil ; c-basic-offset:8 -*- */
  2. /*
  3. * Hotplug functions for libusb
  4. * Copyright (C) 2012-2013 Nathan Hjelm <hjelmn@mac.com>
  5. * Copyright (C) 2012-2013 Peter Stuge <peter@stuge.se>
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. #include <config.h>
  22. #include <errno.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <sys/types.h>
  27. #include <assert.h>
  28. #include "libusbi.h"
  29. #include "hotplug.h"
  30. /**
  31. * @defgroup hotplug Device hotplug event notification
  32. * This page details how to use the libusb hotplug interface.
  33. *
  34. * \page hotplug Device hotplug event notification
  35. *
  36. * \section intro Introduction
  37. *
  38. * Releases of libusb 1.0 newer than 1.X have added support for hotplug
  39. * events. This interface allows you to request notification for the
  40. * arrival and departure of matching USB devices.
  41. *
  42. * To receive hotplug notification you register a callback by calling
  43. * libusb_hotplug_register_callback(). This function will optionally return
  44. * a handle that can be passed to libusb_hotplug_deregister_callback().
  45. *
  46. * A callback function must return an int (0 or 1) indicating whether the callback is
  47. * expecting additional events. Returning 0 will rearm the callback and 1 will cause
  48. * the callback to be deregistered.
  49. *
  50. * Callbacks for a particulat context are automatically deregistered by libusb_exit().
  51. *
  52. * As of 1.X there are two supported hotplug events:
  53. * - LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: A device has arrived and is ready to use
  54. * - LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: A device has left and is no longer available
  55. *
  56. * A hotplug event can listen for either or both of these events.
  57. *
  58. * Note: If you receive notification that a device has left and you have any
  59. * a libusb_device_handles for the device it is up to you to call libusb_close()
  60. * on each handle to free up any remaining resources associated with the device.
  61. * Once a device has left any libusb_device_handle associated with the device
  62. * are invalid and will remain so even if the device comes back.
  63. *
  64. * When handling a LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED event it is considered
  65. * safe to call any libusb function that takes a libusb_device. On the other hand,
  66. * when handling a LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT event the only safe function
  67. * is libusb_get_device_descriptor().
  68. *
  69. * The following code provides an example of the usage of the hotplug interface:
  70. \code
  71. static int count = 0;
  72. int hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev,
  73. libusb_hotplug_event event, void *user_data) {
  74. static libusb_device_handle *handle = NULL;
  75. struct libusb_device_descriptor desc;
  76. int rc;
  77. (void)libusb_get_device_descriptor(dev, &desc);
  78. if (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED == event) {
  79. rc = libusb_open(dev, &handle);
  80. if (LIBUSB_SUCCESS != rc) {
  81. printf("Could not open USB device\n");
  82. }
  83. } else if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event) {
  84. if (handle) {
  85. libusb_close(handle);
  86. handle = NULL;
  87. }
  88. } else {
  89. printf("Unhandled event %d\n", event);
  90. }
  91. count++;
  92. return 0;
  93. }
  94. int main (void) {
  95. libusb_hotplug_callback_handle handle;
  96. int rc;
  97. libusb_init(NULL);
  98. rc = libusb_hotplug_register_callback(NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |
  99. LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, 0, 0x045a, 0x5005,
  100. LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, NULL,
  101. &handle);
  102. if (LIBUSB_SUCCESS != rc) {
  103. printf("Error creating a hotplug callback\n");
  104. libusb_exit(NULL);
  105. return EXIT_FAILURE;
  106. }
  107. while (count < 2) {
  108. usleep(10000);
  109. }
  110. libusb_hotplug_deregister_callback(handle);
  111. libusb_exit(NULL);
  112. return 0;
  113. }
  114. \endcode
  115. */
  116. static int usbi_hotplug_match_cb (struct libusb_device *dev, libusb_hotplug_event event,
  117. struct libusb_hotplug_callback *hotplug_cb) {
  118. struct libusb_context *ctx = dev->ctx;
  119. /* Handle lazy deregistration of callback */
  120. if (hotplug_cb->needs_free) {
  121. /* Free callback */
  122. return 1;
  123. }
  124. if (!(hotplug_cb->events & event)) {
  125. return 0;
  126. }
  127. if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->vendor_id &&
  128. hotplug_cb->vendor_id != dev->device_descriptor.idVendor) {
  129. return 0;
  130. }
  131. if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->product_id &&
  132. hotplug_cb->product_id != dev->device_descriptor.idProduct) {
  133. return 0;
  134. }
  135. if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->dev_class &&
  136. hotplug_cb->dev_class != dev->device_descriptor.bDeviceClass) {
  137. return 0;
  138. }
  139. return hotplug_cb->cb (ctx == usbi_default_context ? NULL : ctx,
  140. dev, event, hotplug_cb->user_data);
  141. }
  142. void usbi_hotplug_match(struct libusb_device *dev, libusb_hotplug_event event) {
  143. struct libusb_hotplug_callback *hotplug_cb, *next;
  144. struct libusb_context *ctx = dev->ctx;
  145. usbi_mutex_lock(&ctx->hotplug_cbs_lock);
  146. list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) {
  147. usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
  148. int ret = usbi_hotplug_match_cb (dev, event, hotplug_cb);
  149. usbi_mutex_lock(&ctx->hotplug_cbs_lock);
  150. if (ret) {
  151. list_del(&hotplug_cb->list);
  152. free(hotplug_cb);
  153. }
  154. }
  155. usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
  156. /* loop through and disconnect all open handles for this device */
  157. if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event) {
  158. struct libusb_device_handle *handle;
  159. usbi_mutex_lock(&ctx->open_devs_lock);
  160. list_for_each_entry(handle, &ctx->open_devs, list, struct libusb_device_handle) {
  161. if (dev == handle->dev) {
  162. usbi_handle_disconnect (handle);
  163. }
  164. }
  165. usbi_mutex_unlock(&ctx->open_devs_lock);
  166. }
  167. }
  168. int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx,
  169. libusb_hotplug_event events,
  170. libusb_hotplug_flag flags,
  171. int vendor_id, int product_id,
  172. int dev_class,
  173. libusb_hotplug_callback_fn cb_fn,
  174. void *user_data, libusb_hotplug_callback_handle *handle) {
  175. libusb_hotplug_callback *new_callback;
  176. static int handle_id = 1;
  177. /* check for hotplug support */
  178. if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
  179. return LIBUSB_ERROR_NOT_SUPPORTED;
  180. }
  181. /* check for sane values */
  182. if ((LIBUSB_HOTPLUG_MATCH_ANY != vendor_id && (~0xffff & vendor_id)) ||
  183. (LIBUSB_HOTPLUG_MATCH_ANY != product_id && (~0xffff & product_id)) ||
  184. (LIBUSB_HOTPLUG_MATCH_ANY != dev_class && (~0xff & dev_class)) ||
  185. !cb_fn) {
  186. return LIBUSB_ERROR_INVALID_PARAM;
  187. }
  188. USBI_GET_CONTEXT(ctx);
  189. new_callback = (libusb_hotplug_callback *)calloc(1, sizeof (*new_callback));
  190. if (!new_callback) {
  191. return LIBUSB_ERROR_NO_MEM;
  192. }
  193. new_callback->ctx = ctx;
  194. new_callback->vendor_id = vendor_id;
  195. new_callback->product_id = product_id;
  196. new_callback->dev_class = dev_class;
  197. new_callback->flags = flags;
  198. new_callback->events = events;
  199. new_callback->cb = cb_fn;
  200. new_callback->user_data = user_data;
  201. new_callback->needs_free = 0;
  202. usbi_mutex_lock(&ctx->hotplug_cbs_lock);
  203. /* protect the handle by the context hotplug lock. it doesn't matter if the same handle is used for different
  204. contexts only that the handle is unique for this context */
  205. new_callback->handle = handle_id++;
  206. list_add(&new_callback->list, &ctx->hotplug_cbs);
  207. if (flags & LIBUSB_HOTPLUG_ENUMERATE) {
  208. struct libusb_device *dev;
  209. usbi_mutex_lock(&ctx->usb_devs_lock);
  210. list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device) {
  211. (void) usbi_hotplug_match_cb (dev, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, new_callback);
  212. }
  213. usbi_mutex_unlock(&ctx->usb_devs_lock);
  214. }
  215. usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
  216. if (handle) {
  217. *handle = new_callback->handle;
  218. }
  219. return LIBUSB_SUCCESS;
  220. }
  221. void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx, libusb_hotplug_callback_handle handle) {
  222. struct libusb_hotplug_callback *hotplug_cb;
  223. /* check for hotplug support */
  224. if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
  225. return;
  226. }
  227. USBI_GET_CONTEXT(ctx);
  228. usbi_mutex_lock(&ctx->hotplug_cbs_lock);
  229. list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list,
  230. struct libusb_hotplug_callback) {
  231. if (handle == hotplug_cb->handle) {
  232. /* Mark this callback for deregistration */
  233. hotplug_cb->needs_free = 1;
  234. }
  235. }
  236. usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
  237. }
  238. void usbi_hotplug_deregister_all(struct libusb_context *ctx) {
  239. struct libusb_hotplug_callback *hotplug_cb, *next;
  240. usbi_mutex_lock(&ctx->hotplug_cbs_lock);
  241. list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list,
  242. struct libusb_hotplug_callback) {
  243. list_del(&hotplug_cb->list);
  244. free(hotplug_cb);
  245. }
  246. usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
  247. }