Ignore:
Timestamp:
Dec 12, 2016, 6:38:13 PM (8 years ago)
Author:
Silvan Scherrer
Message:

libusb: update trunk to version 1.0.21

Location:
libusb1/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • libusb1/trunk

  • TabularUnified libusb1/trunk/libusb/hotplug.c

    r1876 r1882  
    1 /* -*- Mode: C; indent-tabs-mode:nil ; c-basic-offset:8 -*- */
     1/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */
    22/*
    33 * Hotplug functions for libusb
    4  * Copyright (C) 2012-2013 Nathan Hjelm <hjelmn@mac.com>
    5  * Copyright (C) 2012-2013 Peter Stuge <peter@stuge.se>
     4 * Copyright © 2012-2013 Nathan Hjelm <hjelmn@mac.com>
     5 * Copyright © 2012-2013 Peter Stuge <peter@stuge.se>
    66 *
    77 * This library is free software; you can redistribute it and/or
     
    2626#include <stdlib.h>
    2727#include <string.h>
     28#ifdef HAVE_SYS_TYPES_H
    2829#include <sys/types.h>
     30#endif
    2931#include <assert.h>
    3032
     
    3335
    3436/**
    35  * @defgroup hotplug  Device hotplug event notification
    36  * This page details how to use the libusb hotplug interface.
    37  *
    38  * \page hotplug Device hotplug event notification
    39  *
    40  * \section intro Introduction
    41  *
    42  * Releases of libusb 1.0 newer than 1.X have added support for hotplug
    43  * events. This interface allows you to request notification for the
    44  * arrival and departure of matching USB devices.
     37 * @defgroup libusb_hotplug Device hotplug event notification
     38 * This page details how to use the libusb hotplug interface, where available.
     39 *
     40 * Be mindful that not all platforms currently implement hotplug notification and
     41 * that you should first call on \ref libusb_has_capability() with parameter
     42 * \ref LIBUSB_CAP_HAS_HOTPLUG to confirm that hotplug support is available.
     43 *
     44 * \page libusb_hotplug Device hotplug event notification
     45 *
     46 * \section hotplug_intro Introduction
     47 *
     48 * Version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102, has added support
     49 * for hotplug events on <b>some</b> platforms (you should test if your platform
     50 * supports hotplug notification by calling \ref libusb_has_capability() with
     51 * parameter \ref LIBUSB_CAP_HAS_HOTPLUG).
     52 *
     53 * This interface allows you to request notification for the arrival and departure
     54 * of matching USB devices.
    4555 *
    4656 * To receive hotplug notification you register a callback by calling
    47  * libusb_hotplug_register_callback(). This function will optionally return
    48  * a handle that can be passed to libusb_hotplug_deregister_callback().
     57 * \ref libusb_hotplug_register_callback(). This function will optionally return
     58 * a callback handle that can be passed to \ref libusb_hotplug_deregister_callback().
    4959 *
    5060 * A callback function must return an int (0 or 1) indicating whether the callback is
    5161 * expecting additional events. Returning 0 will rearm the callback and 1 will cause
    52  * the callback to be deregistered.
    53  *
    54  * Callbacks for a particulat context are automatically deregistered by libusb_exit().
    55  *
    56  * As of 1.X there are two supported hotplug events:
     62 * the callback to be deregistered. Note that when callbacks are called from
     63 * libusb_hotplug_register_callback() because of the \ref LIBUSB_HOTPLUG_ENUMERATE
     64 * flag, the callback return value is ignored, iow you cannot cause a callback
     65 * to be deregistered by returning 1 when it is called from
     66 * libusb_hotplug_register_callback().
     67 *
     68 * Callbacks for a particular context are automatically deregistered by libusb_exit().
     69 *
     70 * As of 1.0.16 there are two supported hotplug events:
    5771 *  - LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: A device has arrived and is ready to use
    5872 *  - LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: A device has left and is no longer available
     
    6276 * Note: If you receive notification that a device has left and you have any
    6377 * a libusb_device_handles for the device it is up to you to call libusb_close()
    64  * on each handle to free up any remaining resources associated with the device.
     78 * on each device handle to free up any remaining resources associated with the device.
    6579 * Once a device has left any libusb_device_handle associated with the device
    6680 * are invalid and will remain so even if the device comes back.
    6781 *
    6882 * When handling a LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED event it is considered
    69  * safe to call any libusb function that takes a libusb_device. On the other hand,
    70  * when handling a LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT event the only safe function
     83 * safe to call any libusb function that takes a libusb_device. It also safe to
     84 * open a device and submit asynchronous transfers. However, most other functions
     85 * that take a libusb_device_handle are <b>not</b> safe to call. Examples of such
     86 * functions are any of the \ref libusb_syncio "synchronous API" functions or the blocking
     87 * functions that retrieve various \ref libusb_desc "USB descriptors". These functions must
     88 * be used outside of the context of the hotplug callback.
     89 *
     90 * When handling a LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT event the only safe function
    7191 * is libusb_get_device_descriptor().
    7292 *
    7393 * The following code provides an example of the usage of the hotplug interface:
    7494\code
     95#include <stdio.h>
     96#include <stdlib.h>
     97#include <time.h>
     98#include <libusb.h>
     99
    75100static int count = 0;
    76101
    77102int hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev,
    78103                     libusb_hotplug_event event, void *user_data) {
    79   static libusb_device_handle *handle = NULL;
     104  static libusb_device_handle *dev_handle = NULL;
    80105  struct libusb_device_descriptor desc;
    81106  int rc;
     
    84109
    85110  if (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED == event) {
    86     rc = libusb_open(dev, &handle);
     111    rc = libusb_open(dev, &dev_handle);
    87112    if (LIBUSB_SUCCESS != rc) {
    88113      printf("Could not open USB device\n");
    89114    }
    90115  } else if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event) {
    91     if (handle) {
    92       libusb_close(handle);
    93       handle = NULL;
     116    if (dev_handle) {
     117      libusb_close(dev_handle);
     118      dev_handle = NULL;
    94119    }
    95120  } else {
     
    102127
    103128int main (void) {
    104   libusb_hotplug_callback_handle handle;
     129  libusb_hotplug_callback_handle callback_handle;
    105130  int rc;
    106131
     
    110135                                        LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, 0, 0x045a, 0x5005,
    111136                                        LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, NULL,
    112                                         &handle);
     137                                        &callback_handle);
    113138  if (LIBUSB_SUCCESS != rc) {
    114139    printf("Error creating a hotplug callback\n");
     
    118143
    119144  while (count < 2) {
    120     usleep(10000);
     145    libusb_handle_events_completed(NULL, NULL);
     146    nanosleep(&(struct timespec){0, 10000000UL}, NULL);
    121147  }
    122148
    123   libusb_hotplug_deregister_callback(handle);
     149  libusb_hotplug_deregister_callback(NULL, callback_handle);
    124150  libusb_exit(NULL);
    125151
     
    129155 */
    130156
    131 static int usbi_hotplug_match_cb (struct libusb_device *dev, libusb_hotplug_event event,
    132                                    struct libusb_hotplug_callback *hotplug_cb) {
    133         struct libusb_context *ctx = dev->ctx;
    134 
    135         /* Handle lazy deregistration of callback */
    136         if (hotplug_cb->needs_free) {
    137                 /* Free callback */
    138                 return 1;
    139         }
    140 
    141         if (!(hotplug_cb->events & event)) {
    142                 return 0;
    143         }
    144 
    145         if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->vendor_id &&
    146             hotplug_cb->vendor_id != dev->device_descriptor.idVendor) {
    147                 return 0;
    148         }
    149 
    150         if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->product_id &&
    151             hotplug_cb->product_id != dev->device_descriptor.idProduct) {
    152                 return 0;
    153         }
    154 
    155         if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->dev_class &&
    156             hotplug_cb->dev_class != dev->device_descriptor.bDeviceClass) {
    157                 return 0;
    158         }
    159 
    160         return hotplug_cb->cb (ctx == usbi_default_context ? NULL : ctx,
    161                              dev, event, hotplug_cb->user_data);
    162 }
    163 
    164 void usbi_hotplug_match(struct libusb_device *dev, libusb_hotplug_event event) {
     157static int usbi_hotplug_match_cb (struct libusb_context *ctx,
     158        struct libusb_device *dev, libusb_hotplug_event event,
     159        struct libusb_hotplug_callback *hotplug_cb)
     160{
     161        /* Handle lazy deregistration of callback */
     162        if (hotplug_cb->needs_free) {
     163                /* Free callback */
     164                return 1;
     165        }
     166
     167        if (!(hotplug_cb->events & event)) {
     168                return 0;
     169        }
     170
     171        if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->vendor_id &&
     172            hotplug_cb->vendor_id != dev->device_descriptor.idVendor) {
     173                return 0;
     174        }
     175
     176        if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->product_id &&
     177            hotplug_cb->product_id != dev->device_descriptor.idProduct) {
     178                return 0;
     179        }
     180
     181        if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->dev_class &&
     182            hotplug_cb->dev_class != dev->device_descriptor.bDeviceClass) {
     183                return 0;
     184        }
     185
     186        return hotplug_cb->cb (ctx, dev, event, hotplug_cb->user_data);
     187}
     188
     189void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
     190        libusb_hotplug_event event)
     191{
    165192        struct libusb_hotplug_callback *hotplug_cb, *next;
    166         struct libusb_context *ctx = dev->ctx;
     193        int ret;
    167194
    168195        usbi_mutex_lock(&ctx->hotplug_cbs_lock);
    169196
    170197        list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) {
    171                 usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
    172                 int ret = usbi_hotplug_match_cb (dev, event, hotplug_cb);
    173                 usbi_mutex_lock(&ctx->hotplug_cbs_lock);
    174 
    175                 if (ret) {
    176                         list_del(&hotplug_cb->list);
    177                         free(hotplug_cb);
    178                 }
     198                usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
     199                ret = usbi_hotplug_match_cb (ctx, dev, event, hotplug_cb);
     200                usbi_mutex_lock(&ctx->hotplug_cbs_lock);
     201
     202                if (ret) {
     203                        list_del(&hotplug_cb->list);
     204                        free(hotplug_cb);
     205                }
    179206        }
    180207
    181208        usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
    182209
    183         /* loop through and disconnect all open handles for this device */
    184         if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event) {
    185                 struct libusb_device_handle *handle;
    186 
    187                 usbi_mutex_lock(&ctx->open_devs_lock);
    188                 list_for_each_entry(handle, &ctx->open_devs, list, struct libusb_device_handle) {
    189                         if (dev == handle->dev) {
    190                                 usbi_handle_disconnect (handle);
    191                         }
    192                 }
    193                 usbi_mutex_unlock(&ctx->open_devs_lock);
    194         }
     210        /* the backend is expected to call the callback for each active transfer */
     211}
     212
     213void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev,
     214        libusb_hotplug_event event)
     215{
     216        int pending_events;
     217        libusb_hotplug_message *message = calloc(1, sizeof(*message));
     218
     219        if (!message) {
     220                usbi_err(ctx, "error allocating hotplug message");
     221                return;
     222        }
     223
     224        message->event = event;
     225        message->device = dev;
     226
     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        pending_events = usbi_pending_events(ctx);
     231        list_add_tail(&message->list, &ctx->hotplug_msgs);
     232        if (!pending_events)
     233                usbi_signal_event(ctx);
     234        usbi_mutex_unlock(&ctx->event_data_lock);
    195235}
    196236
    197237int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx,
    198                                                   libusb_hotplug_event events,
    199                                                   libusb_hotplug_flag flags,
    200                                                   int vendor_id, int product_id,
    201                                                   int dev_class,
    202                                                   libusb_hotplug_callback_fn cb_fn,
    203                                                   void *user_data, libusb_hotplug_callback_handle *handle) {
    204         libusb_hotplug_callback *new_callback;
    205         static int handle_id = 1;
    206 
    207         /* check for hotplug support */
    208         if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
    209                 return LIBUSB_ERROR_NOT_SUPPORTED;
    210         }
    211 
    212         /* check for sane values */
    213         if ((LIBUSB_HOTPLUG_MATCH_ANY != vendor_id && (~0xffff & vendor_id)) ||
    214             (LIBUSB_HOTPLUG_MATCH_ANY != product_id && (~0xffff & product_id)) ||
    215             (LIBUSB_HOTPLUG_MATCH_ANY != dev_class && (~0xff & dev_class)) ||
    216             !cb_fn) {
    217                 return LIBUSB_ERROR_INVALID_PARAM;
    218         }
    219 
    220         USBI_GET_CONTEXT(ctx);
    221 
    222         new_callback = (libusb_hotplug_callback *)calloc(1, sizeof (*new_callback));
    223         if (!new_callback) {
    224                 return LIBUSB_ERROR_NO_MEM;
    225         }
    226 
    227         new_callback->ctx = ctx;
    228         new_callback->vendor_id = vendor_id;
    229         new_callback->product_id = product_id;
    230         new_callback->dev_class = dev_class;
    231         new_callback->flags = flags;
    232         new_callback->events = events;
    233         new_callback->cb = cb_fn;
    234         new_callback->user_data = user_data;
    235         new_callback->needs_free = 0;
     238        libusb_hotplug_event events, libusb_hotplug_flag flags,
     239        int vendor_id, int product_id, int dev_class,
     240        libusb_hotplug_callback_fn cb_fn, void *user_data,
     241        libusb_hotplug_callback_handle *callback_handle)
     242{
     243        libusb_hotplug_callback *new_callback;
     244        static int handle_id = 1;
     245
     246        /* check for hotplug support */
     247        if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
     248                return LIBUSB_ERROR_NOT_SUPPORTED;
     249        }
     250
     251        /* check for sane values */
     252        if ((LIBUSB_HOTPLUG_MATCH_ANY != vendor_id && (~0xffff & vendor_id)) ||
     253            (LIBUSB_HOTPLUG_MATCH_ANY != product_id && (~0xffff & product_id)) ||
     254            (LIBUSB_HOTPLUG_MATCH_ANY != dev_class && (~0xff & dev_class)) ||
     255            !cb_fn) {
     256                return LIBUSB_ERROR_INVALID_PARAM;
     257        }
     258
     259        USBI_GET_CONTEXT(ctx);
     260
     261        new_callback = (libusb_hotplug_callback *)calloc(1, sizeof (*new_callback));
     262        if (!new_callback) {
     263                return LIBUSB_ERROR_NO_MEM;
     264        }
     265
     266        new_callback->ctx = ctx;
     267        new_callback->vendor_id = vendor_id;
     268        new_callback->product_id = product_id;
     269        new_callback->dev_class = dev_class;
     270        new_callback->flags = flags;
     271        new_callback->events = events;
     272        new_callback->cb = cb_fn;
     273        new_callback->user_data = user_data;
     274        new_callback->needs_free = 0;
    236275
    237276        usbi_mutex_lock(&ctx->hotplug_cbs_lock);
    238277
    239         /* protect the handle by the context hotplug lock. it doesn't matter if the same handle is used for different
    240           contexts only that the handle is unique for this context */
    241         new_callback->handle = handle_id++;
     278        /* protect the handle by the context hotplug lock. it doesn't matter if the same handle
     279         * is used for different contexts only that the handle is unique for this context */
     280        new_callback->handle = handle_id++;
    242281
    243282        list_add(&new_callback->list, &ctx->hotplug_cbs);
    244283
    245         if (flags & LIBUSB_HOTPLUG_ENUMERATE) {
    246                 struct libusb_device *dev;
    247 
    248                 usbi_mutex_lock(&ctx->usb_devs_lock);
    249 
    250                 list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device) {
    251                         (void) usbi_hotplug_match_cb (dev, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, new_callback);
    252                 }
    253 
    254                 usbi_mutex_unlock(&ctx->usb_devs_lock);
    255         }
    256 
    257284        usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
    258285
    259         if (handle) {
    260                 *handle = new_callback->handle;
    261         }
    262 
    263         return LIBUSB_SUCCESS;
    264 }
    265 
    266 void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx, libusb_hotplug_callback_handle handle) {
    267         struct libusb_hotplug_callback *hotplug_cb;
    268 
    269         /* check for hotplug support */
    270         if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
    271                 return;
    272         }
    273 
    274         USBI_GET_CONTEXT(ctx);
    275 
    276         usbi_mutex_lock(&ctx->hotplug_cbs_lock);
    277         list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list,
    278                             struct libusb_hotplug_callback) {
    279                 if (handle == hotplug_cb->handle) {
    280                         /* Mark this callback for deregistration */
    281                         hotplug_cb->needs_free = 1;
    282                 }
    283         }
    284         usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
     286
     287        if (flags & LIBUSB_HOTPLUG_ENUMERATE) {
     288                int i, len;
     289                struct libusb_device **devs;
     290
     291                len = (int) libusb_get_device_list(ctx, &devs);
     292                if (len < 0) {
     293                        libusb_hotplug_deregister_callback(ctx,
     294                                                        new_callback->handle);
     295                        return len;
     296                }
     297
     298                for (i = 0; i < len; i++) {
     299                        usbi_hotplug_match_cb(ctx, devs[i],
     300                                        LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED,
     301                                        new_callback);
     302                }
     303
     304                libusb_free_device_list(devs, 1);
     305        }
     306
     307
     308        if (callback_handle)
     309                *callback_handle = new_callback->handle;
     310
     311        return LIBUSB_SUCCESS;
     312}
     313
     314void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx,
     315        libusb_hotplug_callback_handle callback_handle)
     316{
     317        struct libusb_hotplug_callback *hotplug_cb;
     318
     319        /* check for hotplug support */
     320        if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
     321                return;
     322        }
     323
     324        USBI_GET_CONTEXT(ctx);
     325
     326        usbi_mutex_lock(&ctx->hotplug_cbs_lock);
     327        list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list,
     328                            struct libusb_hotplug_callback) {
     329                if (callback_handle == hotplug_cb->handle) {
     330                        /* Mark this callback for deregistration */
     331                        hotplug_cb->needs_free = 1;
     332                }
     333        }
     334        usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
     335
     336        usbi_hotplug_notification(ctx, NULL, 0);
    285337}
    286338
     
    292344                                 struct libusb_hotplug_callback) {
    293345                list_del(&hotplug_cb->list);
    294                 free(hotplug_cb);
     346                free(hotplug_cb);
    295347        }
    296348
Note: See TracChangeset for help on using the changeset viewer.