hotplug.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. /* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */
  2. /*
  3. * Hotplug functions for libusb
  4. * Copyright © 2012-2021 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 "libusbi.h"
  22. /**
  23. * @defgroup libusb_hotplug Device hotplug event notification
  24. * This page details how to use the libusb hotplug interface, where available.
  25. *
  26. * Be mindful that not all platforms currently implement hotplug notification and
  27. * that you should first call on \ref libusb_has_capability() with parameter
  28. * \ref LIBUSB_CAP_HAS_HOTPLUG to confirm that hotplug support is available.
  29. *
  30. * \page libusb_hotplug Device hotplug event notification
  31. *
  32. * \section hotplug_intro Introduction
  33. *
  34. * Version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102, has added support
  35. * for hotplug events on <b>some</b> platforms (you should test if your platform
  36. * supports hotplug notification by calling \ref libusb_has_capability() with
  37. * parameter \ref LIBUSB_CAP_HAS_HOTPLUG).
  38. *
  39. * This interface allows you to request notification for the arrival and departure
  40. * of matching USB devices.
  41. *
  42. * To receive hotplug notification you register a callback by calling
  43. * \ref libusb_hotplug_register_callback(). This function will optionally return
  44. * a callback handle that can be passed to \ref 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. Note that when callbacks are called from
  49. * libusb_hotplug_register_callback() because of the \ref LIBUSB_HOTPLUG_ENUMERATE
  50. * flag, the callback return value is ignored. In other words, you cannot cause a
  51. * callback to be deregistered by returning 1 when it is called from
  52. * libusb_hotplug_register_callback().
  53. *
  54. * Callbacks for a particular context are automatically deregistered by libusb_exit().
  55. *
  56. * As of 1.0.16 there are two supported hotplug events:
  57. * - LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: A device has arrived and is ready to use
  58. * - LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: A device has left and is no longer available
  59. *
  60. * A hotplug event can listen for either or both of these events.
  61. *
  62. * Note: If you receive notification that a device has left and you have any
  63. * libusb_device_handles for the device it is up to you to call libusb_close()
  64. * on each device handle to free up any remaining resources associated with the device.
  65. * Once a device has left any libusb_device_handle associated with the device
  66. * are invalid and will remain so even if the device comes back.
  67. *
  68. * When handling a LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED event it is considered
  69. * safe to call any libusb function that takes a libusb_device. It also safe to
  70. * open a device and submit asynchronous transfers. However, most other functions
  71. * that take a libusb_device_handle are <b>not</b> safe to call. Examples of such
  72. * functions are any of the \ref libusb_syncio "synchronous API" functions or the blocking
  73. * functions that retrieve various \ref libusb_desc "USB descriptors". These functions must
  74. * be used outside of the context of the hotplug callback.
  75. *
  76. * When handling a LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT event the only safe function
  77. * is libusb_get_device_descriptor().
  78. *
  79. * The following code provides an example of the usage of the hotplug interface:
  80. \code
  81. #include <stdio.h>
  82. #include <stdlib.h>
  83. #include <time.h>
  84. #include <libusb.h>
  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 *dev_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, &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 (dev_handle) {
  99. libusb_close(dev_handle);
  100. dev_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 callback_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. &callback_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. libusb_handle_events_completed(NULL, NULL);
  123. nanosleep(&(struct timespec){0, 10000000UL}, NULL);
  124. }
  125. libusb_hotplug_deregister_callback(NULL, callback_handle);
  126. libusb_exit(NULL);
  127. return 0;
  128. }
  129. \endcode
  130. */
  131. #define VALID_HOTPLUG_EVENTS \
  132. (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | \
  133. LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT)
  134. #define VALID_HOTPLUG_FLAGS \
  135. (LIBUSB_HOTPLUG_ENUMERATE)
  136. void usbi_hotplug_init(struct libusb_context *ctx)
  137. {
  138. /* check for hotplug support */
  139. if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG))
  140. return;
  141. usbi_mutex_init(&ctx->hotplug_cbs_lock);
  142. list_init(&ctx->hotplug_cbs);
  143. ctx->next_hotplug_cb_handle = 1;
  144. usbi_atomic_store(&ctx->hotplug_ready, 1);
  145. }
  146. void usbi_hotplug_exit(struct libusb_context *ctx)
  147. {
  148. struct usbi_hotplug_callback *hotplug_cb, *next_cb;
  149. struct usbi_hotplug_message *msg;
  150. struct libusb_device *dev, *next_dev;
  151. /* check for hotplug support */
  152. if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG))
  153. return;
  154. if (!usbi_atomic_load(&ctx->hotplug_ready))
  155. return;
  156. /* free all registered hotplug callbacks */
  157. for_each_hotplug_cb_safe(ctx, hotplug_cb, next_cb) {
  158. list_del(&hotplug_cb->list);
  159. free(hotplug_cb);
  160. }
  161. /* free all pending hotplug messages */
  162. while (!list_empty(&ctx->hotplug_msgs)) {
  163. msg = list_first_entry(&ctx->hotplug_msgs, struct usbi_hotplug_message, list);
  164. /* if the device left, the message holds a reference
  165. * and we must drop it */
  166. if (msg->event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT)
  167. libusb_unref_device(msg->device);
  168. list_del(&msg->list);
  169. free(msg);
  170. }
  171. /* free all discovered devices. due to parent references loop until no devices are freed. */
  172. for_each_device_safe(ctx, dev, next_dev) {
  173. /* remove the device from the usb_devs list only if there are no
  174. * references held, otherwise leave it on the list so that a
  175. * warning message will be shown */
  176. if (usbi_atomic_load(&dev->refcnt) == 1) {
  177. list_del(&dev->list);
  178. }
  179. if (dev->parent_dev && usbi_atomic_load(&dev->parent_dev->refcnt) == 1) {
  180. /* the parent was before this device in the list and will be released.
  181. remove it from the list. this is safe as parent_dev can not be
  182. equal to next_dev. */
  183. assert (dev->parent_dev != next_dev);
  184. list_del(&dev->parent_dev->list);
  185. }
  186. libusb_unref_device(dev);
  187. }
  188. usbi_mutex_destroy(&ctx->hotplug_cbs_lock);
  189. }
  190. static int usbi_hotplug_match_cb(struct libusb_device *dev,
  191. libusb_hotplug_event event, struct usbi_hotplug_callback *hotplug_cb)
  192. {
  193. if (!(hotplug_cb->flags & event)) {
  194. return 0;
  195. }
  196. if ((hotplug_cb->flags & USBI_HOTPLUG_VENDOR_ID_VALID) &&
  197. hotplug_cb->vendor_id != dev->device_descriptor.idVendor) {
  198. return 0;
  199. }
  200. if ((hotplug_cb->flags & USBI_HOTPLUG_PRODUCT_ID_VALID) &&
  201. hotplug_cb->product_id != dev->device_descriptor.idProduct) {
  202. return 0;
  203. }
  204. if ((hotplug_cb->flags & USBI_HOTPLUG_DEV_CLASS_VALID) &&
  205. hotplug_cb->dev_class != dev->device_descriptor.bDeviceClass) {
  206. return 0;
  207. }
  208. return hotplug_cb->cb(DEVICE_CTX(dev), dev, event, hotplug_cb->user_data);
  209. }
  210. void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev,
  211. libusb_hotplug_event event)
  212. {
  213. struct usbi_hotplug_message *msg;
  214. unsigned int event_flags;
  215. /* Only generate a notification if hotplug is ready. This prevents hotplug
  216. * notifications from being generated during initial enumeration or if the
  217. * backend does not support hotplug. */
  218. if (!usbi_atomic_load(&ctx->hotplug_ready))
  219. return;
  220. msg = calloc(1, sizeof(*msg));
  221. if (!msg) {
  222. usbi_err(ctx, "error allocating hotplug message");
  223. return;
  224. }
  225. msg->event = event;
  226. msg->device = dev;
  227. /* Take the event data lock and add this message to the list.
  228. * Only signal an event if there are no prior pending events. */
  229. usbi_mutex_lock(&ctx->event_data_lock);
  230. event_flags = ctx->event_flags;
  231. ctx->event_flags |= USBI_EVENT_HOTPLUG_MSG_PENDING;
  232. list_add_tail(&msg->list, &ctx->hotplug_msgs);
  233. if (!event_flags)
  234. usbi_signal_event(&ctx->event);
  235. usbi_mutex_unlock(&ctx->event_data_lock);
  236. }
  237. void usbi_hotplug_process(struct libusb_context *ctx, struct list_head *hotplug_msgs)
  238. {
  239. struct usbi_hotplug_callback *hotplug_cb, *next_cb;
  240. struct usbi_hotplug_message *msg;
  241. int r;
  242. usbi_mutex_lock(&ctx->hotplug_cbs_lock);
  243. /* dispatch all pending hotplug messages */
  244. while (!list_empty(hotplug_msgs)) {
  245. msg = list_first_entry(hotplug_msgs, struct usbi_hotplug_message, list);
  246. for_each_hotplug_cb_safe(ctx, hotplug_cb, next_cb) {
  247. /* skip callbacks that have unregistered */
  248. if (hotplug_cb->flags & USBI_HOTPLUG_NEEDS_FREE)
  249. continue;
  250. usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
  251. r = usbi_hotplug_match_cb(msg->device, msg->event, hotplug_cb);
  252. usbi_mutex_lock(&ctx->hotplug_cbs_lock);
  253. if (r) {
  254. list_del(&hotplug_cb->list);
  255. free(hotplug_cb);
  256. }
  257. }
  258. /* if the device left, the message holds a reference
  259. * and we must drop it */
  260. if (msg->event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT)
  261. libusb_unref_device(msg->device);
  262. list_del(&msg->list);
  263. free(msg);
  264. }
  265. /* free any callbacks that have unregistered */
  266. for_each_hotplug_cb_safe(ctx, hotplug_cb, next_cb) {
  267. if (hotplug_cb->flags & USBI_HOTPLUG_NEEDS_FREE) {
  268. usbi_dbg(ctx, "freeing hotplug cb %p with handle %d",
  269. hotplug_cb, hotplug_cb->handle);
  270. list_del(&hotplug_cb->list);
  271. free(hotplug_cb);
  272. }
  273. }
  274. usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
  275. }
  276. int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx,
  277. int events, int flags,
  278. int vendor_id, int product_id, int dev_class,
  279. libusb_hotplug_callback_fn cb_fn, void *user_data,
  280. libusb_hotplug_callback_handle *callback_handle)
  281. {
  282. struct usbi_hotplug_callback *hotplug_cb;
  283. /* check for sane values */
  284. if (!events || (~VALID_HOTPLUG_EVENTS & events) ||
  285. (~VALID_HOTPLUG_FLAGS & flags) ||
  286. (LIBUSB_HOTPLUG_MATCH_ANY != vendor_id && (~0xffff & vendor_id)) ||
  287. (LIBUSB_HOTPLUG_MATCH_ANY != product_id && (~0xffff & product_id)) ||
  288. (LIBUSB_HOTPLUG_MATCH_ANY != dev_class && (~0xff & dev_class)) ||
  289. !cb_fn) {
  290. return LIBUSB_ERROR_INVALID_PARAM;
  291. }
  292. /* check for hotplug support */
  293. if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG))
  294. return LIBUSB_ERROR_NOT_SUPPORTED;
  295. ctx = usbi_get_context(ctx);
  296. hotplug_cb = calloc(1, sizeof(*hotplug_cb));
  297. if (!hotplug_cb)
  298. return LIBUSB_ERROR_NO_MEM;
  299. hotplug_cb->flags = (uint8_t)events;
  300. if (LIBUSB_HOTPLUG_MATCH_ANY != vendor_id) {
  301. hotplug_cb->flags |= USBI_HOTPLUG_VENDOR_ID_VALID;
  302. hotplug_cb->vendor_id = (uint16_t)vendor_id;
  303. }
  304. if (LIBUSB_HOTPLUG_MATCH_ANY != product_id) {
  305. hotplug_cb->flags |= USBI_HOTPLUG_PRODUCT_ID_VALID;
  306. hotplug_cb->product_id = (uint16_t)product_id;
  307. }
  308. if (LIBUSB_HOTPLUG_MATCH_ANY != dev_class) {
  309. hotplug_cb->flags |= USBI_HOTPLUG_DEV_CLASS_VALID;
  310. hotplug_cb->dev_class = (uint8_t)dev_class;
  311. }
  312. hotplug_cb->cb = cb_fn;
  313. hotplug_cb->user_data = user_data;
  314. usbi_mutex_lock(&ctx->hotplug_cbs_lock);
  315. /* protect the handle by the context hotplug lock */
  316. hotplug_cb->handle = ctx->next_hotplug_cb_handle++;
  317. /* handle the unlikely case of overflow */
  318. if (ctx->next_hotplug_cb_handle < 0)
  319. ctx->next_hotplug_cb_handle = 1;
  320. list_add(&hotplug_cb->list, &ctx->hotplug_cbs);
  321. usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
  322. usbi_dbg(ctx, "new hotplug cb %p with handle %d", hotplug_cb, hotplug_cb->handle);
  323. if ((flags & LIBUSB_HOTPLUG_ENUMERATE) && (events & LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED)) {
  324. ssize_t i, len;
  325. struct libusb_device **devs;
  326. len = libusb_get_device_list(ctx, &devs);
  327. if (len < 0) {
  328. libusb_hotplug_deregister_callback(ctx, hotplug_cb->handle);
  329. return (int)len;
  330. }
  331. for (i = 0; i < len; i++) {
  332. usbi_hotplug_match_cb(devs[i],
  333. LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED,
  334. hotplug_cb);
  335. }
  336. libusb_free_device_list(devs, 1);
  337. }
  338. if (callback_handle)
  339. *callback_handle = hotplug_cb->handle;
  340. return LIBUSB_SUCCESS;
  341. }
  342. void API_EXPORTED libusb_hotplug_deregister_callback(libusb_context *ctx,
  343. libusb_hotplug_callback_handle callback_handle)
  344. {
  345. struct usbi_hotplug_callback *hotplug_cb;
  346. int deregistered = 0;
  347. /* check for hotplug support */
  348. if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG))
  349. return;
  350. usbi_dbg(ctx, "deregister hotplug cb %d", callback_handle);
  351. ctx = usbi_get_context(ctx);
  352. usbi_mutex_lock(&ctx->hotplug_cbs_lock);
  353. for_each_hotplug_cb(ctx, hotplug_cb) {
  354. if (callback_handle == hotplug_cb->handle) {
  355. /* mark this callback for deregistration */
  356. hotplug_cb->flags |= USBI_HOTPLUG_NEEDS_FREE;
  357. deregistered = 1;
  358. break;
  359. }
  360. }
  361. usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
  362. if (deregistered) {
  363. unsigned int event_flags;
  364. usbi_mutex_lock(&ctx->event_data_lock);
  365. event_flags = ctx->event_flags;
  366. ctx->event_flags |= USBI_EVENT_HOTPLUG_CB_DEREGISTERED;
  367. if (!event_flags)
  368. usbi_signal_event(&ctx->event);
  369. usbi_mutex_unlock(&ctx->event_data_lock);
  370. }
  371. }
  372. DEFAULT_VISIBILITY
  373. void * LIBUSB_CALL libusb_hotplug_get_user_data(libusb_context *ctx,
  374. libusb_hotplug_callback_handle callback_handle)
  375. {
  376. struct usbi_hotplug_callback *hotplug_cb;
  377. void *user_data = NULL;
  378. /* check for hotplug support */
  379. if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG))
  380. return NULL;
  381. usbi_dbg(ctx, "get hotplug cb %d user data", callback_handle);
  382. ctx = usbi_get_context(ctx);
  383. usbi_mutex_lock(&ctx->hotplug_cbs_lock);
  384. for_each_hotplug_cb(ctx, hotplug_cb) {
  385. if (callback_handle == hotplug_cb->handle) {
  386. user_data = hotplug_cb->user_data;
  387. break;
  388. }
  389. }
  390. usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
  391. return user_data;
  392. }