27#include <winpr/cmdline.h> 
   28#include <winpr/collections.h> 
   30#include <freerdp/addin.h> 
   32#include "urbdrc_types.h" 
   33#include "urbdrc_main.h" 
   35#include "libusb_udevice.h" 
   39#if !defined(LIBUSB_HOTPLUG_NO_FLAGS) 
   40#define LIBUSB_HOTPLUG_NO_FLAGS 0 
   43#define BASIC_STATE_FUNC_DEFINED(_arg, _type)                   \ 
   44  static _type udevman_get_##_arg(IUDEVMAN* idevman)          \ 
   46    UDEVMAN* udevman = (UDEVMAN*)idevman;                   \ 
   47    return udevman->_arg;                                   \ 
   49  static void udevman_set_##_arg(IUDEVMAN* idevman, _type _t) \ 
   51    UDEVMAN* udevman = (UDEVMAN*)idevman;                   \ 
   55#define BASIC_STATE_FUNC_REGISTER(_arg, _man)    \ 
   56  _man->iface.get_##_arg = udevman_get_##_arg; \ 
   57  (_man)->iface.set_##_arg = udevman_set_##_arg 
   73  LPCSTR devices_vid_pid;
 
   75  wArrayList* hotplug_vid_pids;
 
   78  UINT32 next_device_id;
 
   81  HANDLE devman_loading;
 
   82  libusb_context* context;
 
   86typedef UDEVMAN* PUDEVMAN;
 
   88static BOOL poll_libusb_events(UDEVMAN* udevman);
 
   90static void udevman_rewind(IUDEVMAN* idevman)
 
   92  UDEVMAN* udevman = (UDEVMAN*)idevman;
 
   93  udevman->idev = udevman->head;
 
   96static BOOL udevman_has_next(IUDEVMAN* idevman)
 
   98  UDEVMAN* udevman = (UDEVMAN*)idevman;
 
  100  if (!udevman || !udevman->idev)
 
  106static IUDEVICE* udevman_get_next(IUDEVMAN* idevman)
 
  108  UDEVMAN* udevman = (UDEVMAN*)idevman;
 
  109  IUDEVICE* pdev = NULL;
 
  110  pdev = udevman->idev;
 
  111  udevman->idev = (IUDEVICE*)((
UDEVICE*)udevman->idev)->next;
 
  115static IUDEVICE* udevman_get_udevice_by_addr(IUDEVMAN* idevman, BYTE bus_number, BYTE dev_number)
 
  117  IUDEVICE* dev = NULL;
 
  122  idevman->loading_lock(idevman);
 
  123  idevman->rewind(idevman);
 
  125  while (idevman->has_next(idevman))
 
  127    IUDEVICE* pdev = idevman->get_next(idevman);
 
  129    if ((pdev->get_bus_number(pdev) == bus_number) &&
 
  130        (pdev->get_dev_number(pdev) == dev_number))
 
  137  idevman->loading_unlock(idevman);
 
  141static size_t udevman_register_udevice(IUDEVMAN* idevman, BYTE bus_number, BYTE dev_number,
 
  142                                       UINT16 idVendor, UINT16 idProduct, UINT32 flag)
 
  144  UDEVMAN* udevman = (UDEVMAN*)idevman;
 
  145  IUDEVICE* pdev = NULL;
 
  146  IUDEVICE** devArray = NULL;
 
  151  if (!idevman || !idevman->plugin)
 
  155  pdev = udevman_get_udevice_by_addr(idevman, bus_number, dev_number);
 
  160  if (flag & UDEVMAN_FLAG_ADD_BY_ADDR)
 
  163    IUDEVICE* tdev = udev_new_by_addr(urbdrc, udevman->context, bus_number, dev_number);
 
  168    id = idevman->get_next_device_id(idevman);
 
  169    tdev->set_UsbDevice(tdev, 
id);
 
  170    idevman->loading_lock(idevman);
 
  172    if (udevman->head == NULL)
 
  175      udevman->head = tdev;
 
  176      udevman->tail = tdev;
 
  181      udevman->tail->set_p_next(udevman->tail, tdev);
 
  182      tdev->set_p_prev(tdev, udevman->tail);
 
  183      udevman->tail = tdev;
 
  186    udevman->device_num += 1;
 
  187    idevman->loading_unlock(idevman);
 
  189  else if (flag & UDEVMAN_FLAG_ADD_BY_VID_PID)
 
  193    num = udev_new_by_id(urbdrc, udevman->context, idVendor, idProduct, &devArray);
 
  197      WLog_Print(urbdrc->log, WLOG_WARN,
 
  198                 "Could not find or redirect any usb devices by id %04x:%04x", idVendor,
 
  202    for (
size_t i = 0; i < num; i++)
 
  205      IUDEVICE* tdev = devArray[i];
 
  207      if (udevman_get_udevice_by_addr(idevman, tdev->get_bus_number(tdev),
 
  208                                      tdev->get_dev_number(tdev)) != NULL)
 
  215      id = idevman->get_next_device_id(idevman);
 
  216      tdev->set_UsbDevice(tdev, 
id);
 
  217      idevman->loading_lock(idevman);
 
  219      if (udevman->head == NULL)
 
  222        udevman->head = tdev;
 
  223        udevman->tail = tdev;
 
  228        udevman->tail->set_p_next(udevman->tail, tdev);
 
  229        tdev->set_p_prev(tdev, udevman->tail);
 
  230        udevman->tail = tdev;
 
  233      udevman->device_num += 1;
 
  234      idevman->loading_unlock(idevman);
 
  238    free((
void*)devArray);
 
  243    WLog_Print(urbdrc->log, WLOG_ERROR, 
"udevman_register_udevice: Invalid flag=%08" PRIx32,
 
  251static BOOL udevman_unregister_udevice(IUDEVMAN* idevman, BYTE bus_number, BYTE dev_number)
 
  253  UDEVMAN* udevman = (UDEVMAN*)idevman;
 
  255  UDEVICE* dev = (
UDEVICE*)udevman_get_udevice_by_addr(idevman, bus_number, dev_number);
 
  257  if (!dev || !idevman)
 
  260  idevman->loading_lock(idevman);
 
  261  idevman->rewind(idevman);
 
  263  while (idevman->has_next(idevman))
 
  265    pdev = (
UDEVICE*)idevman->get_next(idevman);
 
  270      if (dev->prev != NULL)
 
  274        pdev->next = dev->next;
 
  279        udevman->head = (IUDEVICE*)dev->next;
 
  284      if (dev->next != NULL)
 
  288        pdev->prev = dev->prev;
 
  293        udevman->tail = (IUDEVICE*)dev->prev;
 
  296      udevman->device_num--;
 
  301  idevman->loading_unlock(idevman);
 
  305    dev->iface.free(&dev->iface);
 
  313static BOOL udevman_unregister_all_udevices(IUDEVMAN* idevman)
 
  315  UDEVMAN* udevman = (UDEVMAN*)idevman;
 
  323  idevman->loading_lock(idevman);
 
  324  idevman->rewind(idevman);
 
  326  while (idevman->has_next(idevman))
 
  334    if (dev->prev != NULL)
 
  338      pdev->next = dev->next;
 
  343      udevman->head = (IUDEVICE*)dev->next;
 
  348    if (dev->next != NULL)
 
  352      pdev->prev = dev->prev;
 
  357      udevman->tail = (IUDEVICE*)dev->prev;
 
  360    dev->iface.free(&dev->iface);
 
  361    udevman->device_num--;
 
  364  idevman->loading_unlock(idevman);
 
  369static int udevman_is_auto_add(IUDEVMAN* idevman)
 
  371  UDEVMAN* udevman = (UDEVMAN*)idevman;
 
  372  return (udevman->flags & UDEVMAN_FLAG_ADD_BY_AUTO) ? 1 : 0;
 
  375static IUDEVICE* udevman_get_udevice_by_UsbDevice(IUDEVMAN* idevman, UINT32 UsbDevice)
 
  380  if (!idevman || !idevman->plugin)
 
  384  UsbDevice = UsbDevice & INTERFACE_ID_MASK;
 
  386  idevman->loading_lock(idevman);
 
  387  idevman->rewind(idevman);
 
  389  while (idevman->has_next(idevman))
 
  391    pdev = (
UDEVICE*)idevman->get_next(idevman);
 
  393    if (pdev->UsbDevice == UsbDevice)
 
  395      idevman->loading_unlock(idevman);
 
  396      return (IUDEVICE*)pdev;
 
  400  idevman->loading_unlock(idevman);
 
  401  WLog_Print(urbdrc->log, WLOG_WARN, 
"Failed to find a USB device mapped to deviceId=%08" PRIx32,
 
  406static IUDEVICE* udevman_get_udevice_by_ChannelID(IUDEVMAN* idevman, UINT32 channelID)
 
  411  if (!idevman || !idevman->plugin)
 
  416  idevman->loading_lock(idevman);
 
  417  idevman->rewind(idevman);
 
  419  while (idevman->has_next(idevman))
 
  421    pdev = (
UDEVICE*)idevman->get_next(idevman);
 
  423    if (pdev->channelID == channelID)
 
  425      idevman->loading_unlock(idevman);
 
  426      return (IUDEVICE*)pdev;
 
  430  idevman->loading_unlock(idevman);
 
  431  WLog_Print(urbdrc->log, WLOG_WARN, 
"Failed to find a USB device mapped to channelID=%08" PRIx32,
 
  436static void udevman_loading_lock(IUDEVMAN* idevman)
 
  438  UDEVMAN* udevman = (UDEVMAN*)idevman;
 
  439  (void)WaitForSingleObject(udevman->devman_loading, INFINITE);
 
  442static void udevman_loading_unlock(IUDEVMAN* idevman)
 
  444  UDEVMAN* udevman = (UDEVMAN*)idevman;
 
  445  (void)ReleaseMutex(udevman->devman_loading);
 
  448BASIC_STATE_FUNC_DEFINED(device_num, UINT32)
 
  450static UINT32 udevman_get_next_device_id(IUDEVMAN* idevman)
 
  452  UDEVMAN* udevman = (UDEVMAN*)idevman;
 
  453  return udevman->next_device_id++;
 
  456static void udevman_set_next_device_id(IUDEVMAN* idevman, UINT32 _t)
 
  458  UDEVMAN* udevman = (UDEVMAN*)idevman;
 
  459  udevman->next_device_id = _t;
 
  462static void udevman_free(IUDEVMAN* idevman)
 
  464  UDEVMAN* udevman = (UDEVMAN*)idevman;
 
  469  udevman->running = FALSE;
 
  472    (void)WaitForSingleObject(udevman->thread, INFINITE);
 
  473    (void)CloseHandle(udevman->thread);
 
  476  udevman_unregister_all_udevices(idevman);
 
  478  if (udevman->devman_loading)
 
  479    (void)CloseHandle(udevman->devman_loading);
 
  481  libusb_exit(udevman->context);
 
  483  ArrayList_Free(udevman->hotplug_vid_pids);
 
  487static BOOL filter_by_class(uint8_t bDeviceClass, uint8_t bDeviceSubClass)
 
  489  switch (bDeviceClass)
 
  491    case LIBUSB_CLASS_AUDIO:
 
  492    case LIBUSB_CLASS_HID:
 
  493    case LIBUSB_CLASS_MASS_STORAGE:
 
  494    case LIBUSB_CLASS_HUB:
 
  495    case LIBUSB_CLASS_SMART_CARD:
 
  501  switch (bDeviceSubClass)
 
  510static BOOL append(
char* dst, 
size_t length, 
const char* src)
 
  512  return winpr_str_append(src, dst, length, NULL);
 
  515static BOOL device_is_filtered(
struct libusb_device* dev,
 
  516                               const struct libusb_device_descriptor* desc,
 
  517                               libusb_hotplug_event event)
 
  519  char buffer[8192] = { 0 };
 
  521  BOOL filtered = FALSE;
 
  522  append(buffer, 
sizeof(buffer), usb_interface_class_to_string(desc->bDeviceClass));
 
  523  if (filter_by_class(desc->bDeviceClass, desc->bDeviceSubClass))
 
  526  switch (desc->bDeviceClass)
 
  528    case LIBUSB_CLASS_PER_INTERFACE:
 
  530      struct libusb_config_descriptor* config = NULL;
 
  531      int rc = libusb_get_active_config_descriptor(dev, &config);
 
  532      if (rc == LIBUSB_SUCCESS)
 
  534        for (uint8_t x = 0; x < config->bNumInterfaces; x++)
 
  536          const struct libusb_interface* ifc = &config->interface[x];
 
  537          for (
int y = 0; y < ifc->num_altsetting; y++)
 
  539            const struct libusb_interface_descriptor* 
const alt = &ifc->altsetting[y];
 
  540            if (filter_by_class(alt->bInterfaceClass, alt->bInterfaceSubClass))
 
  543            append(buffer, 
sizeof(buffer), 
"|");
 
  544            append(buffer, 
sizeof(buffer),
 
  545                   usb_interface_class_to_string(alt->bInterfaceClass));
 
  549      libusb_free_config_descriptor(config);
 
  562      case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT:
 
  563        what = 
"Hotplug remove";
 
  565      case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED:
 
  566        what = 
"Hotplug add";
 
  569        what = 
"Hotplug unknown";
 
  574  WLog_DBG(TAG, 
"%s device VID=0x%04X,PID=0x%04X class %s", what, desc->idVendor, desc->idProduct,
 
  579static int LIBUSB_CALL hotplug_callback(
struct libusb_context* ctx, 
struct libusb_device* dev,
 
  580                                        libusb_hotplug_event event, 
void* user_data)
 
  583  struct libusb_device_descriptor desc;
 
  584  UDEVMAN* udevman = (UDEVMAN*)user_data;
 
  585  const uint8_t bus = libusb_get_bus_number(dev);
 
  586  const uint8_t addr = libusb_get_device_address(dev);
 
  587  int rc = libusb_get_device_descriptor(dev, &desc);
 
  591  if (rc != LIBUSB_SUCCESS)
 
  596    case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED:
 
  597      pair.vid = desc.idVendor;
 
  598      pair.pid = desc.idProduct;
 
  599      if ((ArrayList_Contains(udevman->hotplug_vid_pids, &pair)) ||
 
  600          (udevman->iface.isAutoAdd(&udevman->iface) &&
 
  601           !device_is_filtered(dev, &desc, event)))
 
  603        add_device(&udevman->iface, DEVICE_ADD_FLAG_ALL, bus, addr, desc.idVendor,
 
  608    case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT:
 
  609      del_device(&udevman->iface, DEVICE_ADD_FLAG_ALL, bus, addr, desc.idVendor,
 
  620static BOOL udevman_initialize(IUDEVMAN* idevman, UINT32 channelId)
 
  622  UDEVMAN* udevman = (UDEVMAN*)idevman;
 
  627  idevman->status &= (uint32_t)~URBDRC_DEVICE_CHANNEL_CLOSED;
 
  628  idevman->controlChannelId = channelId;
 
  632static BOOL udevman_vid_pid_pair_equals(
const void* objA, 
const void* objB)
 
  634  const VID_PID_PAIR* a = objA;
 
  635  const VID_PID_PAIR* b = objB;
 
  637  return (a->vid == b->vid) && (a->pid == b->pid);
 
  640static BOOL udevman_parse_device_id_addr(
const char** str, UINT16* id1, UINT16* id2, UINT16 max,
 
  641                                         char split_sign, 
char delimiter)
 
  645  unsigned long rc = 0;
 
  647  rc = strtoul(*str, &mid, 16);
 
  649  if ((mid == *str) || (*mid != split_sign) || (rc > max))
 
  653  rc = strtoul(++mid, &end, 16);
 
  655  if ((end == mid) || (rc > max))
 
  663  if (*end == delimiter)
 
  672static UINT urbdrc_udevman_register_devices(UDEVMAN* udevman, 
const char* devices, BOOL add_by_addr)
 
  674  const char* pos = devices;
 
  680    if (!udevman_parse_device_id_addr(&pos, &id1, &id2, (add_by_addr) ? UINT8_MAX : UINT16_MAX,
 
  683      WLog_ERR(TAG, 
"Invalid device argument: \"%s\"", devices);
 
  684      return CHANNEL_RC_INITIALIZATION_ERROR;
 
  689      if (!add_device(&udevman->iface, DEVICE_ADD_FLAG_BUS | DEVICE_ADD_FLAG_DEV, (UINT8)id1,
 
  691        return CHANNEL_RC_INITIALIZATION_ERROR;
 
  695      VID_PID_PAIR* idpair = calloc(1, 
sizeof(VID_PID_PAIR));
 
  697        return CHANNEL_RC_NO_MEMORY;
 
  700      if (!ArrayList_Append(udevman->hotplug_vid_pids, idpair))
 
  703        return CHANNEL_RC_NO_MEMORY;
 
  707      if (!add_device(&udevman->iface, DEVICE_ADD_FLAG_VENDOR | DEVICE_ADD_FLAG_PRODUCT, 0, 0,
 
  711        return CHANNEL_RC_INITIALIZATION_ERROR;
 
  717  return CHANNEL_RC_OK;
 
  720static UINT urbdrc_udevman_parse_addin_args(UDEVMAN* udevman, 
const ADDIN_ARGV* args)
 
  722  LPCSTR devices = NULL;
 
  724  for (
int x = 0; x < args->argc; x++)
 
  726    const char* arg = args->argv[x];
 
  727    if (strcmp(arg, 
"dbg") == 0)
 
  729      WLog_SetLogLevel(WLog_Get(TAG), WLOG_TRACE);
 
  731    else if (_strnicmp(arg, 
"device:", 7) == 0)
 
  734      const char* val = &arg[7];
 
  735      const size_t len = strlen(val);
 
  736      if (strcmp(val, 
"*") == 0)
 
  738        udevman->flags |= UDEVMAN_FLAG_ADD_BY_AUTO;
 
  740      else if (_strnicmp(arg, 
"USBInstanceID:", 14) == 0)
 
  744      else if ((val[0] == 
'{') && (val[len - 1] == 
'}'))
 
  749    else if (_strnicmp(arg, 
"dev:", 4) == 0)
 
  753    else if (_strnicmp(arg, 
"id", 2) == 0)
 
  755      const char* p = strchr(arg, 
':');
 
  757        udevman->devices_vid_pid = p + 1;
 
  759        udevman->flags = UDEVMAN_FLAG_ADD_BY_VID_PID;
 
  761    else if (_strnicmp(arg, 
"addr", 4) == 0)
 
  763      const char* p = strchr(arg, 
':');
 
  765        udevman->devices_addr = p + 1;
 
  767        udevman->flags = UDEVMAN_FLAG_ADD_BY_ADDR;
 
  769    else if (strcmp(arg, 
"auto") == 0)
 
  771      udevman->flags |= UDEVMAN_FLAG_ADD_BY_AUTO;
 
  775      const size_t len = strlen(arg);
 
  776      if ((arg[0] == 
'{') && (arg[len - 1] == 
'}'))
 
  784    if (udevman->flags & UDEVMAN_FLAG_ADD_BY_VID_PID)
 
  785      udevman->devices_vid_pid = devices;
 
  786    else if (udevman->flags & UDEVMAN_FLAG_ADD_BY_ADDR)
 
  787      udevman->devices_addr = devices;
 
  790  return CHANNEL_RC_OK;
 
  793static UINT udevman_listener_created_callback(IUDEVMAN* iudevman)
 
  795  UDEVMAN* udevman = (UDEVMAN*)iudevman;
 
  796  WINPR_ASSERT(udevman);
 
  798  if (udevman->devices_vid_pid)
 
  799    return urbdrc_udevman_register_devices(udevman, udevman->devices_vid_pid, FALSE);
 
  801  if (udevman->devices_addr)
 
  802    return urbdrc_udevman_register_devices(udevman, udevman->devices_addr, TRUE);
 
  804  return CHANNEL_RC_OK;
 
  807static void udevman_load_interface(UDEVMAN* udevman)
 
  810  udevman->iface.free = udevman_free;
 
  812  udevman->iface.rewind = udevman_rewind;
 
  813  udevman->iface.get_next = udevman_get_next;
 
  814  udevman->iface.has_next = udevman_has_next;
 
  815  udevman->iface.register_udevice = udevman_register_udevice;
 
  816  udevman->iface.unregister_udevice = udevman_unregister_udevice;
 
  817  udevman->iface.get_udevice_by_UsbDevice = udevman_get_udevice_by_UsbDevice;
 
  818  udevman->iface.get_udevice_by_ChannelID = udevman_get_udevice_by_ChannelID;
 
  820  udevman->iface.isAutoAdd = udevman_is_auto_add;
 
  822  BASIC_STATE_FUNC_REGISTER(device_num, udevman);
 
  823  BASIC_STATE_FUNC_REGISTER(next_device_id, udevman);
 
  826  udevman->iface.loading_lock = udevman_loading_lock;
 
  827  udevman->iface.loading_unlock = udevman_loading_unlock;
 
  828  udevman->iface.initialize = udevman_initialize;
 
  829  udevman->iface.listener_created_callback = udevman_listener_created_callback;
 
  832static BOOL poll_libusb_events(UDEVMAN* udevman)
 
  834  int rc = LIBUSB_SUCCESS;
 
  835  struct timeval tv = { 0, 500 };
 
  836  if (libusb_try_lock_events(udevman->context) == 0)
 
  838    if (libusb_event_handling_ok(udevman->context))
 
  840      rc = libusb_handle_events_locked(udevman->context, &tv);
 
  841      if (rc != LIBUSB_SUCCESS)
 
  842        WLog_WARN(TAG, 
"libusb_handle_events_locked %d", rc);
 
  844    libusb_unlock_events(udevman->context);
 
  848    libusb_lock_event_waiters(udevman->context);
 
  849    if (libusb_event_handler_active(udevman->context))
 
  851      rc = libusb_wait_for_event(udevman->context, &tv);
 
  852      if (rc < LIBUSB_SUCCESS)
 
  853        WLog_WARN(TAG, 
"libusb_wait_for_event %d", rc);
 
  855    libusb_unlock_event_waiters(udevman->context);
 
  861static DWORD WINAPI poll_thread(LPVOID lpThreadParameter)
 
  863  libusb_hotplug_callback_handle handle = 0;
 
  864  UDEVMAN* udevman = (UDEVMAN*)lpThreadParameter;
 
  865  BOOL hasHotplug = libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG);
 
  869    int rc = libusb_hotplug_register_callback(
 
  871        LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
 
  872        LIBUSB_HOTPLUG_NO_FLAGS, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,
 
  873        LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, udevman, &handle);
 
  875    if (rc != LIBUSB_SUCCESS)
 
  876      udevman->running = FALSE;
 
  879    WLog_WARN(TAG, 
"Platform does not support libusb hotplug. USB devices plugged in later " 
  880                   "will not be detected.");
 
  882  while (udevman->running)
 
  884    poll_libusb_events(udevman);
 
  888    libusb_hotplug_deregister_callback(udevman->context, handle);
 
  891  while (poll_libusb_events(udevman))
 
  898FREERDP_ENTRY_POINT(UINT VCAPITYPE libusb_freerdp_urbdrc_client_subsystem_entry(
 
  903  UDEVMAN* udevman = NULL;
 
  905  udevman = (PUDEVMAN)calloc(1, 
sizeof(UDEVMAN));
 
  910  udevman->hotplug_vid_pids = ArrayList_New(TRUE);
 
  911  if (!udevman->hotplug_vid_pids)
 
  913  obj = ArrayList_Object(udevman->hotplug_vid_pids);
 
  914  obj->fnObjectFree = free;
 
  915  obj->fnObjectEquals = udevman_vid_pid_pair_equals;
 
  917  udevman->next_device_id = BASE_USBDEVICE_NUM;
 
  918  udevman->iface.plugin = pEntryPoints->plugin;
 
  919  const int res = libusb_init(&udevman->context);
 
  921  if (res != LIBUSB_SUCCESS)
 
  925#if LIBUSB_API_VERSION >= 0x01000106 
  927  const int rc = libusb_set_option(udevman->context, LIBUSB_OPTION_USE_USBDK);
 
  932    case LIBUSB_ERROR_NOT_FOUND:
 
  933    case LIBUSB_ERROR_NOT_SUPPORTED:
 
  934      WLog_WARN(TAG, 
"LIBUSB_OPTION_USE_USBDK %s [%d]", libusb_strerror(rc), rc);
 
  937      WLog_ERR(TAG, 
"LIBUSB_OPTION_USE_USBDK %s [%d]", libusb_strerror(rc), rc);
 
  943  udevman->flags = UDEVMAN_FLAG_ADD_BY_VID_PID;
 
  944  udevman->devman_loading = CreateMutexA(NULL, FALSE, 
"devman_loading");
 
  946  if (!udevman->devman_loading)
 
  950  udevman_load_interface(udevman);
 
  951  status = urbdrc_udevman_parse_addin_args(udevman, args);
 
  953  if (status != CHANNEL_RC_OK)
 
  956  udevman->running = TRUE;
 
  957  udevman->thread = CreateThread(NULL, 0, poll_thread, udevman, 0, NULL);
 
  959  if (!udevman->thread)
 
  962  if (!pEntryPoints->pRegisterUDEVMAN(pEntryPoints->plugin, (IUDEVMAN*)udevman))
 
  965  WLog_DBG(TAG, 
"UDEVMAN device registered.");
 
  968  udevman_free(&udevman->iface);
 
  969  return ERROR_INTERNAL_ERROR;
 
This struct contains function pointer to initialize/free objects.