hotplug.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */
  2. /*
  3. * Hotplug functions for libusbx
  4. * Copyright © 2012-2013 Nathan Hjelm <hjelmn@mac.com>
  5. * Copyright © 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. #ifdef HAVE_SYS_TYPES_H
  27. #include <sys/types.h>
  28. #endif
  29. #include <assert.h>
  30. #include "libusbi.h"
  31. #include "hotplug.h"
  32. /**
  33. * @defgroup hotplug Device hotplug event notification
  34. * This page details how to use the libusb hotplug interface, where available.
  35. *
  36. * Be mindful that not all platforms currently implement hotplug notification and
  37. * that you should first call on \ref libusb_has_capability() with parameter
  38. * \ref LIBUSB_CAP_HAS_HOTPLUG to confirm that hotplug support is available.
  39. *
  40. * \page hotplug Device hotplug event notification
  41. *
  42. * \section intro Introduction
  43. *
  44. * Version 1.0.16, \ref LIBUSBX_API_VERSION >= 0x01000102, has added support
  45. * for hotplug events on <b>some</b> platforms (you should test if your platform
  46. * supports hotplug notification by calling \ref libusb_has_capability() with
  47. * parameter \ref LIBUSB_CAP_HAS_HOTPLUG).
  48. *
  49. * This interface allows you to request notification for the arrival and departure
  50. * of matching USB devices.
  51. *
  52. * To receive hotplug notification you register a callback by calling
  53. * \ref libusb_hotplug_register_callback(). This function will optionally return
  54. * a handle that can be passed to \ref libusb_hotplug_deregister_callback().
  55. *
  56. * A callback function must return an int (0 or 1) indicating whether the callback is
  57. * expecting additional events. Returning 0 will rearm the callback and 1 will cause
  58. * the callback to be deregistered. Note that when callbacks are called from
  59. * libusb_hotplug_register_callback() because of the \ref LIBUSB_HOTPLUG_ENUMERATE
  60. * flag, the callback return value is ignored, iow you cannot cause a callback
  61. * to be deregistered by returning 1 when it is called from
  62. * libusb_hotplug_register_callback().
  63. *
  64. * Callbacks for a particular context are automatically deregistered by libusb_exit().
  65. *
  66. * As of 1.0.16 there are two supported hotplug events:
  67. * - LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: A device has arrived and is ready to use
  68. * - LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: A device has left and is no longer available
  69. *
  70. * A hotplug event can listen for either or both of these events.
  71. *
  72. * Note: If you receive notification that a device has left and you have any
  73. * a libusb_device_handles for the device it is up to you to call libusb_close()
  74. * on each handle to free up any remaining resources associated with the device.
  75. * Once a device has left any libusb_device_handle associated with the device
  76. * are invalid and will remain so even if the device comes back.
  77. *
  78. * When handling a LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED event it is considered
  79. * safe to call any libusbx function that takes a libusb_device. On the other hand,
  80. * when handling a LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT event the only safe function
  81. * is libusb_get_device_descriptor().
  82. *
  83. * The following code provides an example of the usage of the hotplug interface:
  84. \code
  85. static int count = 0;
  86. int hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev,
  87. libusb_hotplug_event event, void *user_data) {
  88. static libusb_device_handle *handle = NULL;
  89. struct libusb_device_descriptor desc;
  90. int rc;
  91. (void)libusb_get_device_descriptor(dev, &desc);
  92. if (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED == event) {
  93. rc = libusb_open(dev, &handle);
  94. if (LIBUSB_SUCCESS != rc) {
  95. printf("Could not open USB device\n");
  96. }
  97. } else if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event) {
  98. if (handle) {
  99. libusb_close(handle);
  100. handle = NULL;
  101. }
  102. } else {
  103. printf("Unhandled event %d\n", event);
  104. }
  105. count++;
  106. return 0;
  107. }
  108. int main (void) {
  109. libusb_hotplug_callback_handle handle;
  110. int rc;
  111. libusb_init(NULL);
  112. rc = libusb_hotplug_register_callback(NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |
  113. LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, 0, 0x045a, 0x5005,
  114. LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, NULL,
  115. &handle);
  116. if (LIBUSB_SUCCESS != rc) {
  117. printf("Error creating a hotplug callback\n");
  118. libusb_exit(NULL);
  119. return EXIT_FAILURE;
  120. }
  121. while (count < 2) {
  122. usleep(10000);
  123. }
  124. libusb_hotplug_deregister_callback(handle);
  125. libusb_exit(NULL);
  126. return 0;
  127. }
  128. \endcode
  129. */
  130. static int usbi_hotplug_match_cb (struct libusb_context *ctx,
  131. struct libusb_device *dev, libusb_hotplug_event event,
  132. struct libusb_hotplug_callback *hotplug_cb)
  133. {
  134. /* Handle lazy deregistration of callback */
  135. if (hotplug_cb->needs_free) {
  136. /* Free callback */
  137. return 1;
  138. }
  139. if (!(hotplug_cb->events & event)) {
  140. return 0;
  141. }
  142. if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->vendor_id &&
  143. hotplug_cb->vendor_id != dev->device_descriptor.idVendor) {
  144. return 0;
  145. }
  146. if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->product_id &&
  147. hotplug_cb->product_id != dev->device_descriptor.idProduct) {
  148. return 0;
  149. }
  150. if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->dev_class &&
  151. hotplug_cb->dev_class != dev->device_descriptor.bDeviceClass) {
  152. return 0;
  153. }
  154. return hotplug_cb->cb (ctx, dev, event, hotplug_cb->user_data);
  155. }
  156. void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
  157. libusb_hotplug_event event)
  158. {
  159. struct libusb_hotplug_callback *hotplug_cb, *next;
  160. int ret;
  161. usbi_mutex_lock(&ctx->hotplug_cbs_lock);
  162. list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) {
  163. usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
  164. ret = usbi_hotplug_match_cb (ctx, dev, event, hotplug_cb);
  165. usbi_mutex_lock(&ctx->hotplug_cbs_lock);
  166. if (ret) {
  167. list_del(&hotplug_cb->list);
  168. free(hotplug_cb);
  169. }
  170. }
  171. usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
  172. /* the backend is expected to call the callback for each active transfer */
  173. }
  174. int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx,
  175. libusb_hotplug_event events, libusb_hotplug_flag flags,
  176. int vendor_id, int product_id, int dev_class,
  177. libusb_hotplug_callback_fn cb_fn, void *user_data,
  178. libusb_hotplug_callback_handle *handle)
  179. {
  180. libusb_hotplug_callback *new_callback;
  181. static int handle_id = 1;
  182. /* check for hotplug support */
  183. if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
  184. return LIBUSB_ERROR_NOT_SUPPORTED;
  185. }
  186. /* check for sane values */
  187. if ((LIBUSB_HOTPLUG_MATCH_ANY != vendor_id && (~0xffff & vendor_id)) ||
  188. (LIBUSB_HOTPLUG_MATCH_ANY != product_id && (~0xffff & product_id)) ||
  189. (LIBUSB_HOTPLUG_MATCH_ANY != dev_class && (~0xff & dev_class)) ||
  190. !cb_fn) {
  191. return LIBUSB_ERROR_INVALID_PARAM;
  192. }
  193. USBI_GET_CONTEXT(ctx);
  194. new_callback = (libusb_hotplug_callback *)calloc(1, sizeof (*new_callback));
  195. if (!new_callback) {
  196. return LIBUSB_ERROR_NO_MEM;
  197. }
  198. new_callback->ctx = ctx;
  199. new_callback->vendor_id = vendor_id;
  200. new_callback->product_id = product_id;
  201. new_callback->dev_class = dev_class;
  202. new_callback->flags = flags;
  203. new_callback->events = events;
  204. new_callback->cb = cb_fn;
  205. new_callback->user_data = user_data;
  206. new_callback->needs_free = 0;
  207. usbi_mutex_lock(&ctx->hotplug_cbs_lock);
  208. /* protect the handle by the context hotplug lock. it doesn't matter if the same handle
  209. * is used for different contexts only that the handle is unique for this context */
  210. new_callback->handle = handle_id++;
  211. list_add(&new_callback->list, &ctx->hotplug_cbs);
  212. usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
  213. if (flags & LIBUSB_HOTPLUG_ENUMERATE) {
  214. int i, len;
  215. struct libusb_device **devs;
  216. len = (int) libusb_get_device_list(ctx, &devs);
  217. if (len < 0) {
  218. libusb_hotplug_deregister_callback(ctx,
  219. new_callback->handle);
  220. return len;
  221. }
  222. for (i = 0; i < len; i++) {
  223. usbi_hotplug_match_cb(ctx, devs[i],
  224. LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED,
  225. new_callback);
  226. }
  227. libusb_free_device_list(devs, 1);
  228. }
  229. if (handle) {
  230. *handle = new_callback->handle;
  231. }
  232. return LIBUSB_SUCCESS;
  233. }
  234. void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx,
  235. libusb_hotplug_callback_handle handle)
  236. {
  237. struct libusb_hotplug_callback *hotplug_cb;
  238. libusb_hotplug_message message;
  239. ssize_t ret;
  240. /* check for hotplug support */
  241. if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
  242. return;
  243. }
  244. USBI_GET_CONTEXT(ctx);
  245. usbi_mutex_lock(&ctx->hotplug_cbs_lock);
  246. list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list,
  247. struct libusb_hotplug_callback) {
  248. if (handle == hotplug_cb->handle) {
  249. /* Mark this callback for deregistration */
  250. hotplug_cb->needs_free = 1;
  251. }
  252. }
  253. usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
  254. /* wakeup handle_events to do the actual free */
  255. memset(&message, 0, sizeof(message));
  256. ret = usbi_write(ctx->hotplug_pipe[1], &message, sizeof(message));
  257. if (sizeof(message) != ret) {
  258. usbi_err(ctx, "error writing hotplug message");
  259. }
  260. }
  261. void usbi_hotplug_deregister_all(struct libusb_context *ctx) {
  262. struct libusb_hotplug_callback *hotplug_cb, *next;
  263. usbi_mutex_lock(&ctx->hotplug_cbs_lock);
  264. list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list,
  265. struct libusb_hotplug_callback) {
  266. list_del(&hotplug_cb->list);
  267. free(hotplug_cb);
  268. }
  269. usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
  270. }