229N/A/*
229N/A * CDDL HEADER START
229N/A *
229N/A * The contents of this file are subject to the terms of the
229N/A * Common Development and Distribution License (the "License").
229N/A * You may not use this file except in compliance with the License.
229N/A *
229N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
229N/A * or http://www.opensolaris.org/os/licensing.
229N/A * See the License for the specific language governing permissions
229N/A * and limitations under the License.
229N/A *
229N/A * When distributing Covered Code, include this CDDL HEADER in each
229N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
229N/A * If applicable, add the following below this CDDL HEADER, with the
229N/A * fields enclosed by brackets "[]" replaced with your own identifying
229N/A * information: Portions Copyright [yyyy] [name of copyright owner]
229N/A *
229N/A * CDDL HEADER END
229N/A */
229N/A/*
229N/A * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
229N/A */
229N/A
229N/A#include <stdlib.h>
229N/A#include <stdio.h>
229N/A#include <sys/types.h>
229N/A#include <dirent.h>
229N/A#include <errno.h>
229N/A#include <strings.h>
229N/A#include <dlfcn.h>
229N/A#include <thread.h>
229N/A#include <synch.h>
229N/A#include <stdarg.h>
229N/A#include "usb.h"
229N/A#include "wr_libusb.h"
229N/A
229N/A/*
229N/A * libusb wrapper library
229N/A *
229N/A * Implements the libusb specification and calls into platform dependent
229N/A * library implementations of sunray and solaris.
229N/A *
229N/A * Loads the .so's found in the default directory or pointed
229N/A * to by the environment variable SUN_LIBUSBPLUGIN_DIR
229N/A * If there are problems with the module then unload
229N/A * the module and continue
229N/A *
229N/A * Reads plugin versions from the libusb_version variable
229N/A * Reads plugin prefixes from libusb_prefix variable
229N/A * Calls libusb_init implementation of the plugin to determine whether
229N/A * the plugin bus is supported, unsupported, or exclusive.
229N/A * This is from the return values 0, -1, 2
229N/A *
229N/A * In the exclusive case all others plugins will be disabled
229N/A * Case1: ret = PLUGIN_EXCLUSIVE [2]:
229N/A * Sun Ray Environment where server bus is not requested
229N/A * via an environment variable
229N/A * Case2: ret = FAILURE [-1]
229N/A * In the failure case the scenario is an app running
229N/A * in a workstation where the sunray bus cannot be made available.
229N/A * Case3: ret = SUCCESS [0]:
229N/A * All busses are supported
229N/A *
229N/A * The plugins implement certain policies to determine whether access
229N/A * to their bus will be granted and how.
229N/A * These policies are internal to the plugin and not relevant to the wrapper
229N/A * The wrapper merely supports the implementation of these policies
229N/A * via environment variables and init return values.
229N/A *
229N/A * Loads all the symbols of the plugins and maps apps calls -> plugin
229N/A *
229N/A * The wrapper library maintains the open device handle states to be
229N/A * able to map the device handle to the correct plugin. As such each
229N/A * open and close results in updates to the dev handle list.
229N/A *
229N/A */
229N/A
229N/A
229N/Astatic int read_plugin_entries(void);
229N/Astatic int load_plugin_syms(plugin_info_t *, void *, int);
229N/Astatic void wusb_symbol(char **, int, char *, char *);
229N/Astatic int get_pindex(struct usb_dev_handle *, const char *);
229N/Astatic void unload_plugin(int);
229N/Astatic int load_plugins();
229N/Astatic int get_index_devicep(struct usb_device *);
229N/Astatic int get_index_devhdl(struct usb_dev_handle *);
229N/Astatic int usb_add_dev(struct usb_dev_handle *, struct usb_device *, int);
229N/Astatic void usb_del_dev(struct usb_dev_handle *, int);
229N/Astatic int check_sym_hdl(int, int);
229N/Astatic void *lookup_sym_hdl(usb_dev_handle *, int, const char *);
229N/Astatic void usb_dprintf(int level, char *format, ...);
229N/Astatic int is_libusb_plugin(char *);
229N/A
229N/Astatic int libusb_debug = DEBUG_NONE;
229N/Astruct usb_bus *usb_busses;
229N/Astatic mutex_t bus_lock = DEFAULTMUTEX;
229N/Astatic wrapper_info_t winfo;
229N/Astatic plugin_info_t p_info[MAX_PLUGINS];
229N/A
229N/A#ifdef _LP64
229N/A
229N/A#define PLUGIN_PREFIX "/64/"
229N/A
229N/A#else /* _LP64 */
229N/A
229N/A#define PLUGIN_PREFIX ""
229N/A
229N/A#endif /* _LP64 */
229N/A
229N/A
229N/A/*
229N/A * Reads the plugin libraries from the specified dir
229N/A * or the user supplied SUN_LIBUSBPLUGIN_DIR
229N/A * populates the p_name and p_path fields of the array of plugin_info structs
229N/A * increments the array index pindex after each .so is read
229N/A * returns -1(FAILURE) on error
229N/A */
229N/Astatic int
229N/Aread_plugin_entries()
229N/A{
229N/A int pindex = 0;
229N/A int plugin_found = 0;
229N/A char *alt_dir;
229N/A DIR *dirp;
229N/A struct dirent *dp;
229N/A char *tmpplugindir = PLUGIN_DIR;
229N/A char *suffix;
229N/A char modpath[PATH_MAX + 1];
229N/A char plugindir[PATH_MAX + 1];
229N/A
229N/A if ((alt_dir = getenv("SUN_LIBUSBPLUGIN_DIR")) != NULL) {
229N/A tmpplugindir = alt_dir;
229N/A }
229N/A
229N/A if (strnlen(tmpplugindir, PATH_MAX) >
229N/A (PATH_MAX - sizeof (PLUGIN_PREFIX))) {
229N/A usb_dprintf(DEBUG_FUNCTIONS,
229N/A "Invalid plugin directory: %s\n", tmpplugindir);
229N/A
229N/A return (FAILURE);
229N/A }
229N/A
229N/A /*
229N/A * Construct the plugin directory
229N/A * Default plugin for 32 bit: /usr/lib/libusb_plugins/
229N/A * for 64 bit: /usr/lib/libusb_plugins/64/
229N/A *
229N/A * If SUN_LIBUSBPLUGIN_DIR is set, the plugin is:
229N/A * 32bit: SUN_LIBUSBPLUGIN_DIR/
229N/A * 64bit: SUN_LIBUSBPLUGIN_DIR/64/
229N/A */
229N/A snprintf(plugindir, PATH_MAX, "%s%s", tmpplugindir,
229N/A PLUGIN_PREFIX);
229N/A
229N/A usb_dprintf(DEBUG_FUNCTIONS, "plugins dir: %s\n", plugindir);
229N/A
229N/A if ((dirp = opendir(plugindir)) == NULL) {
229N/A usb_dprintf(DEBUG_ERRORS, "%s: %s \n",
229N/A plugindir, strerror(errno));
229N/A return (FAILURE);
229N/A }
229N/A while (dirp) {
229N/A errno = 0;
229N/A if ((dp = readdir(dirp)) != NULL) {
229N/A usb_dprintf(DEBUG_FUNCTIONS,
229N/A "reading entry %s\n", dp->d_name);
229N/A
229N/A /* skip . and .. entries */
229N/A if (strncmp(dp->d_name, ".", 1) == 0) {
229N/A continue;
229N/A }
229N/A if (strncmp(dp->d_name, "..", 2) == 0) {
229N/A continue;
229N/A }
229N/A
229N/A /*
229N/A * Ignore files that are not *.so.X
229N/A * this ensures that libusb.so.1 and plugins.so.1
229N/A * and libusb.so.2 and plugin.so.2 can both be
229N/A * supported
229N/A */
229N/A if ((suffix = strstr(dp->d_name, MOD_SUFFIX)) == NULL) {
229N/A continue;
229N/A } else if (suffix[strlen(MOD_SUFFIX)] != '.') {
229N/A usb_dprintf(DEBUG_RECOVERABLE,
229N/A "did not load %s:%s\n",
229N/A plugindir, dp->d_name);
229N/A continue;
229N/A }
229N/A usb_dprintf(DEBUG_FUNCTIONS,
229N/A "reading .so file %s:%s\n", plugindir, dp->d_name);
229N/A p_info[pindex].p_name = strdup(dp->d_name);
229N/A
229N/A /*
229N/A * using PATH_MAX len here
229N/A */
229N/A if (strlen(p_info[pindex].p_name) > PATH_MAX) {
229N/A usb_dprintf(DEBUG_RECOVERABLE,
229N/A "pathname > PATH_MAX %s",
229N/A p_info[pindex].p_name);
229N/A /* go on to try read next module */
229N/A free(p_info[pindex].p_name);
229N/A continue;
229N/A }
229N/A (void) strncpy(modpath, plugindir, PATH_MAX);
229N/A (void) strncat(modpath, "/", 1);
229N/A (void) strncat(modpath,
229N/A p_info[pindex].p_name, PATH_MAX);
229N/A p_info[pindex].p_path = strdup(modpath);
229N/A usb_dprintf(DEBUG_FUNCTIONS,
229N/A "Path is %s\n", p_info[pindex].p_path);
229N/A
229N/A /*
229N/A * If we do not detect a valid libusb plugin
229N/A * then let's skip and continue
229N/A * do not update pindex if we want to continue
229N/A * we will dlopen and dlclose in this check
229N/A */
229N/A if (is_libusb_plugin(p_info[pindex].p_path) !=
229N/A SUCCESS) {
229N/A free(p_info[pindex].p_path);
229N/A free(p_info[pindex].p_name);
229N/A continue;
229N/A }
229N/A plugin_found = 1;
229N/A if (++pindex == MAX_PLUGINS) {
229N/A usb_dprintf(DEBUG_FUNCTIONS,
229N/A "Max plugins read %d\n", pindex);
229N/A break;
229N/A }
229N/A } else {
229N/A if (errno == 0) {
229N/A (void) closedir(dirp);
229N/A if (!plugin_found) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "No plugin found \n");
229N/A return (FAILURE);
229N/A } else {
229N/A /* end of dir stream */
229N/A return (SUCCESS);
229N/A }
229N/A } else {
229N/A (void) closedir(dirp);
229N/A return (FAILURE);
229N/A }
229N/A }
229N/A }
229N/A return (SUCCESS);
229N/A}
229N/A
229N/A/*
229N/A * In a directory crowded with a lot of .so's
229N/A * filter out potential libusb plugins - helps
229N/A * the plugin loader to only load valid plugins
229N/A * uses the libusb_version symbol as a filter
229N/A */
229N/Astatic int
229N/Ais_libusb_plugin(char *modname)
229N/A{
229N/A void *hdl;
229N/A void *hdl_sym1;
229N/A void *hdl_sym2;
229N/A char *symbol1 = "usb_init";
229N/A char *symbol2 = "libusb_prefix";
229N/A
229N/A hdl = dlopen(modname, RTLD_NOW);
229N/A if (hdl == NULL) {
229N/A usb_dprintf(DEBUG_RECOVERABLE,
229N/A "%s could not be loaded \n", modname);
229N/A return (FAILURE);
229N/A }
229N/A hdl_sym1 = (void *)(dlsym(hdl, symbol1));
229N/A hdl_sym2 = (void *)(dlsym(hdl, symbol2));
229N/A (void) dlclose(hdl);
229N/A if ((hdl_sym1 == NULL) && (hdl_sym2 == NULL)) {
229N/A usb_dprintf(DEBUG_FUNCTIONS,
229N/A "%s not a libusb plugin: unload\n", modname);
229N/A return (FAILURE);
229N/A } else {
229N/A return (SUCCESS);
229N/A }
229N/A}
229N/A
229N/A/*
229N/A * Read the plugin entry names
229N/A * Load the plugins and populate the proper data structures
229N/A * this includes things like bus/dev ptr mappings, handles, etc.
229N/A * Also loads all the symbols also and store the handles
229N/A * Lock: called with bus_lock held
229N/A * called from usb_init
229N/A */
229N/Astatic int
229N/Aload_plugins()
229N/A{
229N/A int pindex = 0;
229N/A void *handle;
229N/A int module_loaded = 0;
229N/A
229N/A if (read_plugin_entries() != SUCCESS) {
229N/A usb_dprintf(DEBUG_FUNCTIONS,
229N/A "Failed to load libusb plugins \n");
229N/A return (FAILURE);
229N/A }
229N/A usb_dprintf(DEBUG_FUNCTIONS,
229N/A "load_plugin: modname is %s\n", p_info[pindex].p_name);
229N/A /*
229N/A * Will load at most MAX_PLUGINS
229N/A */
229N/A while (pindex < MAX_PLUGINS) {
229N/A /* reached the end of modules read into the array */
229N/A if (p_info[pindex].p_name == NULL) {
229N/A break;
229N/A }
229N/A usb_dprintf(DEBUG_FUNCTIONS, "loading:%s pindex:%d\n",
229N/A p_info[pindex].p_name, pindex);
229N/A handle = dlopen(p_info[pindex].p_path, RTLD_NOW);
229N/A if (handle == NULL) {
229N/A usb_dprintf(DEBUG_RECOVERABLE,
229N/A "handle for %s is null\n", p_info[pindex].p_name);
229N/A usb_dprintf(DEBUG_RECOVERABLE, dlerror());
229N/A p_info[pindex].p_handle = NULL;
229N/A free(p_info[pindex].p_name);
229N/A free(p_info[pindex].p_path);
229N/A /* just try to load the next one */
229N/A pindex += 1;
229N/A continue;
229N/A } else {
229N/A p_info[pindex].p_handle = handle;
229N/A }
229N/A if (load_plugin_syms(p_info, handle, pindex) != SUCCESS) {
229N/A usb_dprintf(DEBUG_FUNCTIONS, "Failed to load"
229N/A "symbols for plugin %s\n",
229N/A p_info[pindex].p_name);
229N/A unload_plugin(pindex);
229N/A pindex += 1;
229N/A /* try the next plugin */
229N/A continue;
229N/A }
229N/A module_loaded = 1;
229N/A pindex += 1;
229N/A }
229N/A if (!module_loaded) {
229N/A usb_dprintf(DEBUG_FUNCTIONS, "No module could be loaded \n");
229N/A return (FAILURE);
229N/A } else {
229N/A /* ploaded is the highest index that had a module entry */
229N/A winfo.ploaded = pindex;
229N/A return (SUCCESS);
229N/A }
229N/A}
229N/A
229N/A/*
229N/A * For debugging of bus pointers
229N/A */
229N/Astatic void
229N/Adump_busses()
229N/A{
229N/A struct usb_bus *busp;
229N/A
229N/A for (busp = usb_busses; busp != NULL; busp = busp->next) {
229N/A usb_dprintf(DEBUG_DETAILED, "busp is 0x%x\n", busp);
229N/A }
229N/A}
229N/A
229N/A/*
229N/A * Used to unload plugin
229N/A * calling libusb_fini
229N/A */
229N/Astatic void
229N/Aunload_plugin(int pindex)
229N/A{
229N/A int sym_idx;
229N/A int (*hdl_libusb_fini)(void);
229N/A
229N/A free(p_info[pindex].p_name);
229N/A free(p_info[pindex].p_path);
229N/A p_info[pindex].p_name = NULL;
229N/A
229N/A /* call the plugins libusb_fini here */
229N/A if (check_sym_hdl(pindex, LIBUSB_FINI) < 0) {
229N/A (void) usb_dprintf(DEBUG_RECOVERABLE,
229N/A "hdl_libusb_fini is NULL \n");
229N/A } else {
229N/A hdl_libusb_fini =
229N/A LIBUSB_FINI_CAST(p_info[pindex].sym_hdl[LIBUSB_FINI]);
229N/A (*hdl_libusb_fini)();
229N/A }
229N/A if (p_info[pindex].p_handle != NULL) {
229N/A (void) dlclose(p_info[pindex].p_handle);
229N/A p_info[pindex].exclusive_flag = 0;
229N/A p_info[pindex].active_flag = 0;
229N/A p_info[pindex].p_handle = NULL;
229N/A }
229N/A for (sym_idx = 0; sym_idx < NUM_SYMS; sym_idx ++) {
229N/A p_info[pindex].sym_hdl[sym_idx] = NULL;
229N/A }
229N/A}
229N/A
229N/A/*
229N/A * In trying to map the device handle to a bus
229N/A * walk through the dev handle pointers added
229N/A * during open and find the matching dev handle
229N/A * that exists for that bus. On no match return
229N/A * FAILURE on match return the bus index for this
229N/A * dev handle
229N/A */
229N/Astatic int
229N/Aget_index_devhdl(struct usb_dev_handle *dev)
229N/A{
229N/A int pindex;
229N/A dev_handles_t *devh;
229N/A
229N/A for (pindex = 0; pindex < winfo.ploaded; pindex ++) {
229N/A for (devh = p_info[pindex].dev_handles; devh != NULL;
229N/A devh = devh->next) {
229N/A if (dev == devh->dev) {
229N/A return (pindex);
229N/A }
229N/A }
229N/A }
229N/A return (FAILURE);
229N/A}
229N/A
229N/A/*
229N/A * upon a call to open adds the device handle to the
229N/A * list of handles the wrapper will maintain
229N/A * so that it can map device handles to bus
229N/A * holds bus_lock
229N/A * This is needed simply because we want to able
229N/A * to map the device handles to the plugin module
229N/A */
229N/Astatic int
229N/Ausb_add_dev(struct usb_dev_handle *dev, struct usb_device *device,
229N/A int pindex)
229N/A{
229N/A dev_handles_t *devh, *curr_devh;
229N/A
229N/A (void) mutex_lock(&bus_lock);
229N/A
229N/A /* first device handle to be added */
229N/A if (p_info[pindex].dev_handles == NULL) {
229N/A devh = (dev_handles_t *)malloc(sizeof (dev_handles_t));
229N/A if (devh == NULL) {
229N/A usb_dprintf(DEBUG_FUNCTIONS,
229N/A "Error adding device to list \n");
229N/A (void) mutex_unlock(&bus_lock);
229N/A return (FAILURE);
229N/A }
229N/A p_info[pindex].dev_handles = devh;
229N/A devh->prev = NULL;
229N/A devh->next = NULL;
229N/A } else {
229N/A curr_devh = p_info[pindex].dev_handles;
229N/A while (curr_devh->next != NULL) {
229N/A curr_devh = curr_devh->next;
229N/A }
229N/A /* curr_devh points to last devh handle */
229N/A curr_devh->next = (dev_handles_t *)
229N/A malloc(sizeof (dev_handles_t));
229N/A if (curr_devh->next == NULL) {
229N/A usb_dprintf(DEBUG_FUNCTIONS,
229N/A "Error adding device to list \n");
229N/A (void) mutex_unlock(&bus_lock);
229N/A return (FAILURE);
229N/A }
229N/A devh = curr_devh->next;
229N/A devh->next = NULL;
229N/A devh->prev = curr_devh;
229N/A }
229N/A devh->device = device;
229N/A devh->dev = dev;
229N/A (void) mutex_unlock(&bus_lock);
229N/A
229N/A return (SUCCESS);
229N/A}
229N/A
229N/A/*
229N/A * upon a call to usb_close removes the device handle from the
229N/A * list of handles the wrapper will maintain
229N/A * entries do not get removed on a device removal only on close
229N/A * holds bus_lock
229N/A */
229N/Astatic void
229N/Ausb_del_dev(struct usb_dev_handle *dev, int pindex)
229N/A{
229N/A dev_handles_t *d_dev;
229N/A
229N/A (void) mutex_lock(&bus_lock);
229N/A d_dev = p_info[pindex].dev_handles;
229N/A
229N/A while (d_dev != NULL) {
229N/A if (d_dev->dev == dev) {
229N/A /* Not the last dev hdl */
229N/A if (d_dev->next != NULL) {
229N/A usb_dprintf(DEBUG_DETAILED,
229N/A "d_dev->next != NULL\n");
229N/A d_dev->next->prev = d_dev->prev;
229N/A }
229N/A /* Not the first dev hdl */
229N/A if (d_dev->prev != NULL) {
229N/A usb_dprintf(DEBUG_DETAILED,
229N/A "d_dev->prev != NULL\n");
229N/A d_dev->prev->next = d_dev->next;
229N/A } else {
229N/A /*
229N/A * first dev hdl on list
229N/A * if only handle then point to NULL
229N/A */
229N/A p_info[pindex].dev_handles = d_dev->next;
229N/A if (d_dev->next != NULL) {
229N/A usb_dprintf(DEBUG_DETAILED,
229N/A "d_dev->next != NULL\n");
229N/A d_dev->next->prev = NULL;
229N/A }
229N/A }
229N/A free(d_dev);
229N/A break;
229N/A }
229N/A d_dev = d_dev->next;
229N/A }
229N/A
229N/A (void) mutex_unlock(&bus_lock);
229N/A}
229N/A
229N/A/*
229N/A * checks if a function has a valid symbol handle
229N/A * there also needs to be a valid dlopen hdl for the plugin
229N/A */
229N/Astatic int
229N/Acheck_sym_hdl(int pindex, int sym_index)
229N/A{
229N/A if (p_info[pindex].p_handle == NULL) {
229N/A return (FAILURE);
229N/A } else if (p_info[pindex].sym_hdl[sym_index] == NULL) {
229N/A usb_dprintf(DEBUG_FUNCTIONS,
229N/A "sym_hdl[%d] is null \n", sym_index);
229N/A return (FAILURE);
229N/A } else {
229N/A return (SUCCESS);
229N/A }
229N/A}
229N/A
229N/A/*
229N/A * returns a valid symbol handle or NULL
229N/A */
229N/Astatic void *
229N/Alookup_sym_hdl(usb_dev_handle *dev, int sym_index, const char *func)
229N/A{
229N/A int pindex;
229N/A
229N/A if ((pindex = get_pindex(dev, func)) < 0) {
229N/A return (NULL);
229N/A }
229N/A if (p_info[pindex].p_handle == NULL) {
229N/A return (NULL);
229N/A } else if (p_info[pindex].sym_hdl[sym_index] == NULL) {
229N/A usb_dprintf(DEBUG_FUNCTIONS,
229N/A "sym_hdl[%d] is null \n", sym_index);
229N/A return (NULL);
229N/A } else {
229N/A /* this is needed to support strerror() of last call */
229N/A (void) mutex_lock(&bus_lock);
229N/A winfo.last_pindex = pindex;
229N/A (void) mutex_unlock(&bus_lock);
229N/A return (p_info[pindex].sym_hdl[sym_index]);
229N/A }
229N/A}
229N/A
229N/A/*
229N/A * Used to find the plugin whose bus links this device ptr
229N/A * We will walk the bus list and then traverse the device list
229N/A * of each bus to find the matching device
229N/A * Once we have a match we know the bus that this device hangs off of
229N/A * so we do backtrack and find a match for this bus and plugins.
229N/A * A match means we have a plugin index which essentially tells us
229N/A * the plugin to use
229N/A */
229N/Astatic int
229N/Aget_index_devicep(struct usb_device *device)
229N/A{
229N/A int pindex = 0;
229N/A struct usb_device *devicep;
229N/A struct usb_bus *busp;
229N/A
229N/A busp = usb_busses;
229N/A while (busp != NULL) {
229N/A usb_dprintf(DEBUG_DETAILED,
229N/A "get_index_: busp is 0x%x\n", busp);
229N/A for (devicep = busp->devices; devicep != NULL;
229N/A devicep = devicep->next) {
229N/A usb_dprintf(DEBUG_DETAILED,
229N/A "devicep = 0x%x\n", devicep);
229N/A if (devicep == device) {
229N/A for (pindex = 0; pindex <
229N/A winfo.ploaded; pindex ++) {
229N/A if (p_info[pindex].busp == busp) {
229N/A usb_dprintf(DEBUG_DETAILED,
229N/A "devicep: pindex = %d\n",
229N/A pindex);
229N/A return (pindex);
229N/A }
229N/A }
229N/A }
229N/A }
229N/A busp = busp->next;
229N/A }
229N/A return (FAILURE);
229N/A}
229N/A
229N/Astatic int
229N/Aload_plugin_syms(plugin_info_t *p_info, void *handle, int pindex)
229N/A{
229N/A char *symbol;
229N/A char *prefix;
229N/A int prefix_len = 0;
229N/A int sym_len;
229N/A int sym_idx;
229N/A char **handle_libusb_prefix;
229N/A
229N/A handle_libusb_prefix = (char **)(dlsym(handle, "libusb_prefix"));
229N/A
229N/A /* can have a valid handle but a null prefix */
229N/A if ((handle_libusb_prefix != NULL) &&
229N/A (*handle_libusb_prefix != NULL)) {
229N/A prefix_len = (int)strlen(*handle_libusb_prefix);
229N/A p_info[pindex].prefix = *handle_libusb_prefix;
229N/A } else {
229N/A p_info[pindex].prefix = NULL;
229N/A }
229N/A
229N/A prefix = p_info[pindex].prefix;
229N/A if (prefix != NULL) {
229N/A usb_dprintf(DEBUG_FUNCTIONS,
229N/A "load_plugin_syms():prefix is %s\n", prefix);
229N/A }
229N/A usb_dprintf(DEBUG_DETAILED, "NUM_SYMS is %d\n", NUM_SYMS);
229N/A for (sym_idx = 0; sym_idx < NUM_SYMS; sym_idx ++) {
229N/A sym_len = (int)strlen(sym_names[sym_idx]) + prefix_len + 2;
229N/A symbol = (char *)malloc(sym_len);
229N/A if (symbol == NULL) {
229N/A usb_dprintf(DEBUG_FUNCTIONS,
229N/A "could not alloc space for prefix\n");
229N/A return (FAILURE);
229N/A }
229N/A wusb_symbol(&symbol, sym_len, prefix, sym_names[sym_idx]);
229N/A p_info[pindex].sym_hdl[sym_idx] =
229N/A (void *)dlsym(handle, symbol);
229N/A usb_dprintf(DEBUG_DETAILED, "handle[%d]=0x%x, name = %s\n",
229N/A sym_idx, p_info[pindex].sym_hdl[sym_idx], symbol);
229N/A free(symbol);
229N/A }
229N/A
229N/A return (SUCCESS);
229N/A}
229N/A
229N/A/*
229N/A * Used to form prefixed interface symbols for plugins
229N/A */
229N/Astatic void
229N/Awusb_symbol(char **init_str, int len, char *prefix, char *func_name)
229N/A{
229N/A if (prefix != NULL) {
229N/A (void) snprintf(*init_str, len, "%s", prefix);
229N/A } else {
229N/A (void) memset(*init_str, 0, len);
229N/A }
229N/A (void) strncat(*init_str, func_name, len);
229N/A}
229N/A
229N/A/*
229N/A * Given a device handle map it to a bus
229N/A * if active_index = -1 it means more than
229N/A * a single plugin bus is active so we need
229N/A * walk the dev handles lists. Else active
229N/A * index simply points to the index of the
229N/A * single bus that is active and so we use that
229N/A */
229N/Aint
229N/Aget_pindex(struct usb_dev_handle *dev, const char *func)
229N/A{
229N/A int pindex;
229N/A
229N/A if (dev == NULL) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "%s: Invalid device handle \n", func);
229N/A return (-EINVAL);
229N/A }
229N/A if (winfo.active_index == -1) {
229N/A pindex = get_index_devhdl(dev);
229N/A if (pindex < 0) {
229N/A usb_dprintf(DEBUG_FUNCTIONS,
229N/A "%s: device handle not found\n", func);
229N/A return (-ENODEV);
229N/A }
229N/A } else {
229N/A pindex = winfo.active_index;
229N/A }
229N/A
229N/A return (pindex);
229N/A}
229N/A
229N/A/*
229N/A * Entry points for standard libusb interfaces
229N/A * Given a device handle, device pointer
229N/A * map the device to the bus and call into
229N/A * the loaded module. For calls without
229N/A * arguments - cycle through all modules
229N/A * that are active (per some policies implemented by plugin)
229N/A * and make calls into the implementation specific
229N/A * functions.
229N/A */
229N/A
229N/A/*
229N/A * usb_init() entry point:
229N/A *
229N/A * This will call the libusb-init implementation of each plugin
229N/A * loaded and will determine which busses will be supported.
229N/A * For the plugin busses that are supported usb_init
229N/A * of those plugins will be called. This routine will also
229N/A * invalidate plugin entries that are not supported
229N/A */
229N/Avoid
229N/Ausb_init(void)
229N/A{
229N/A int pindex;
229N/A boolean_t exclusive = 0;
229N/A int (*hdl_libusb_init)(void);
229N/A void (*hdl_usb_init)(void);
229N/A char **hdl_libusb_version;
229N/A int ret;
229N/A char *func = "usb_init";
229N/A char *version;
229N/A char version_store[MAX_VERSION_LEN + 1];
229N/A char wr_version_store[sizeof (LIBUSB_WRAPPER_VERSION)];
229N/A char *token;
229N/A char *wr_token;
229N/A char *debug_str;
229N/A int active_count = 0;
229N/A
229N/A /*
229N/A * If usb_init() already called then do not reinit
229N/A */
229N/A if (winfo.head_busp != NULL) {
229N/A return;
229N/A }
229N/A
229N/A (void) mutex_lock(&bus_lock);
229N/A
229N/A if ((debug_str = getenv("SUN_LIBUSB_DEBUG")) != NULL) {
229N/A libusb_debug = atoi(debug_str);
229N/A }
229N/A usb_dprintf(DEBUG_FUNCTIONS, "the wrapper's debug level is %d\n",
229N/A libusb_debug);
229N/A
229N/A ret = load_plugins();
229N/A if (ret < 0) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "%s: could not load plugin modules\n", func);
229N/A (void) mutex_unlock(&bus_lock);
229N/A return;
229N/A }
229N/A
229N/A winfo.exclusive_index = -1;
229N/A winfo.active_index = -1;
229N/A winfo.head_busp = NULL;
229N/A
229N/A for (pindex = 0; pindex < winfo.ploaded; pindex ++) {
229N/A if (p_info[pindex].p_handle == NULL) {
229N/A continue;
229N/A }
229N/A /* condition for libusb_init not implemented */
229N/A if (check_sym_hdl(pindex, LIBUSB_INIT) < 0) {
229N/A (void) usb_dprintf(DEBUG_RECOVERABLE,
229N/A "hdl_libusb_init is NULL \n");
229N/A p_info[pindex].exclusive_flag = 0;
229N/A p_info[pindex].active_flag = 1;
229N/A active_count += 1;
229N/A continue;
229N/A }
229N/A hdl_libusb_init =
229N/A LIBUSB_INIT_CAST(p_info[pindex].sym_hdl[LIBUSB_INIT]);
229N/A ret = (*hdl_libusb_init)();
229N/A
229N/A (void) usb_dprintf(DEBUG_DETAILED,
229N/A "%s: libusb_init() returned %d\n",
229N/A p_info[pindex].p_name, ret);
229N/A
229N/A switch (ret) {
229N/A case SUCCESS:
229N/A p_info[pindex].exclusive_flag = 0;
229N/A p_info[pindex].active_flag = 1;
229N/A active_count += 1;
229N/A winfo.active_index = pindex;
229N/A break;
229N/A case FAILURE:
229N/A usb_dprintf(DEBUG_FUNCTIONS, "unloading plugin %s\n",
229N/A p_info[pindex].p_name);
229N/A unload_plugin(pindex);
229N/A continue;
229N/A case PLUGIN_EXCLUSIVE:
229N/A /* first plugin to set exclusive */
229N/A if (exclusive != 1) {
229N/A p_info[pindex].exclusive_flag = 1;
229N/A exclusive = 1;
229N/A winfo.exclusive_index = pindex;
229N/A }
229N/A p_info[pindex].active_flag = 1;
229N/A active_count += 1;
229N/A break;
229N/A default:
229N/A usb_dprintf(DEBUG_RECOVERABLE, "unsupported return"
229N/A "value for libusb_init\n");
229N/A }
229N/A
229N/A /*
229N/A * If there is no version defined we accept it
229N/A * but if there is a version mismatch we will skip
229N/A */
229N/A if (check_sym_hdl(pindex, LIBUSB_VERSION) < 0) {
229N/A usb_dprintf(DEBUG_RECOVERABLE,
229N/A "No Version number for plugin found \n");
229N/A } else {
229N/A hdl_libusb_version = (char **)
229N/A (p_info[pindex].sym_hdl[LIBUSB_VERSION]);
229N/A if ((version = *hdl_libusb_version) != NULL) {
229N/A if (strlen(version) > MAX_VERSION_LEN) {
229N/A usb_dprintf(DEBUG_RECOVERABLE,
229N/A "version string exceeds max"
229N/A "characters, truncating\n");
229N/A }
229N/A (void) strncpy(version_store, version,
229N/A MAX_VERSION_LEN);
229N/A token = strtok(version_store, ".");
229N/A (void) strncpy(wr_version_store,
229N/A LIBUSB_WRAPPER_VERSION,
229N/A sizeof (wr_version_store));
229N/A wr_token = strtok(wr_version_store, ".");
229N/A
229N/A /*
229N/A * Initial wrapper version is 1.1
229N/A * if plugin major_rev is != wrapper major_rev
229N/A * then do not load. If the version is not
229N/A * supported set active to FALSE
229N/A */
229N/A usb_dprintf(DEBUG_DETAILED,
229N/A "plugin rev is %d\n", atoi(token));
229N/A usb_dprintf(DEBUG_DETAILED,
229N/A "wrapper rev is %d\n", atoi(wr_token));
229N/A if (atoi(token) != atoi(wr_token)) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "plugin version %s not supported\n",
229N/A version);
229N/A unload_plugin(pindex);
229N/A }
229N/A }
229N/A winfo.last_pindex = pindex;
229N/A }
229N/A if (active_count != 1) {
229N/A winfo.active_index = -1;
229N/A }
229N/A }
229N/A (void) usb_dprintf(DEBUG_DETAILED,
229N/A "winfo.ploaded is %d\n", winfo.ploaded);
229N/A for (pindex = 0; pindex < winfo.ploaded; pindex ++) {
229N/A if (p_info[pindex].p_handle == NULL) {
229N/A continue;
229N/A }
229N/A if (exclusive && p_info[pindex].exclusive_flag == 1) {
229N/A winfo.exclusive_index = pindex;
229N/A winfo.active_index = pindex;
229N/A }
229N/A if (exclusive && p_info[pindex].exclusive_flag != 1) {
229N/A unload_plugin(pindex);
229N/A }
229N/A if (p_info[pindex].active_flag) {
229N/A if (check_sym_hdl(pindex, USB_INIT) < 0) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "could not get symbol for %s\n", func);
229N/A }
229N/A hdl_usb_init = USB_INIT_CAST(p_info[pindex].
229N/A sym_hdl[USB_INIT]);
229N/A (*hdl_usb_init)();
229N/A }
229N/A }
229N/A (void) mutex_unlock(&bus_lock);
229N/A usb_dprintf(DEBUG_DETAILED, "completed usb init()\n");
229N/A}
229N/A
229N/Avoid
229N/Ausb_set_debug(int level)
229N/A{
229N/A int pindex;
229N/A char *func = "usb_set_debug";
229N/A void (*hdl)(int);
229N/A char *debug_str;
229N/A
229N/A /* env debug variables override completely what the app sets */
229N/A if ((debug_str = getenv("SUN_LIBUSB_DEBUG")) != NULL) {
229N/A libusb_debug = atoi(debug_str);
229N/A
229N/A } else {
229N/A
229N/A if (level < 0)
229N/A return;
229N/A
229N/A libusb_debug = level;
229N/A }
229N/A
229N/A usb_dprintf(DEBUG_FUNCTIONS, "libusb debug level is %d\n",
229N/A libusb_debug);
229N/A
229N/A for (pindex = 0; pindex < winfo.ploaded; pindex ++) {
229N/A if (check_sym_hdl(pindex, USB_SET_DEBUG) < 0) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "could not find symbol for %s\n", func);
229N/A continue;
229N/A }
229N/A hdl = USB_SET_DEBUG_CAST
229N/A (p_info[pindex].sym_hdl[USB_SET_DEBUG]);
229N/A (*hdl)(libusb_debug);
229N/A }
229N/A}
229N/A
229N/A/*
229N/A * This will manage the usb_busses pointer for each plugin
229N/A * The wrapper library will expose its own usb_busses pointer
229N/A * This will be built by loading the plugin usb_busses pointer
229N/A * and linking all the bussses. The wrapper libraries usb_bus
229N/A * pointer will in sync every time usb_find_busses is called.
229N/A * Applications are shielded from the underlying plugin usb_busses
229N/A * pointers.
229N/A * ret_bus is supposed to be the number of busses changed
229N/A * since last call
229N/A */
229N/Aint
229N/Ausb_find_busses(void)
229N/A{
229N/A int pindex;
229N/A char *func = "usb_find_busses";
229N/A int (*hdl_usb_find_busses)(void);
229N/A struct usb_bus **hdl_usb_busses;
229N/A int ret_find_busses[MAX_PLUGINS];
229N/A struct usb_bus *tmp_usb_busses = NULL;
229N/A struct usb_bus *mv_usb_busses = NULL;
229N/A struct usb_bus *last_usb_busses = NULL;
229N/A int ret_bus = 0;
229N/A int found_bus = 0;
229N/A
229N/A (void) mutex_lock(&bus_lock);
229N/A
229N/A for (pindex = 0; pindex < winfo.ploaded; pindex ++) {
229N/A if (check_sym_hdl(pindex, USB_FIND_BUSSES) < 0) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "could not get symbol for %s\n", func);
229N/A continue;
229N/A }
229N/A hdl_usb_find_busses =
229N/A USB_FIND_BUSSES_CAST
229N/A (p_info[pindex].sym_hdl[USB_FIND_BUSSES]);
229N/A
229N/A /* calling the find_busses whose symbols can be found */
229N/A ret_find_busses[pindex] = (*hdl_usb_find_busses)();
229N/A ret_bus += ret_find_busses[pindex];
229N/A
229N/A /*
229N/A * updated usb_busses pointer for the plugins
229N/A * this could be NULL
229N/A */
229N/A if (check_sym_hdl(pindex, USB_BUSSES) < 0) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "could not get symbol for %s\n", usb_busses);
229N/A p_info[pindex].busp = NULL;
229N/A continue;
229N/A }
229N/A hdl_usb_busses =
229N/A USB_BUSSES_CAST(p_info[pindex].sym_hdl[USB_BUSSES]);
229N/A p_info[pindex].busp = *hdl_usb_busses;
229N/A usb_dprintf(DEBUG_DETAILED,
229N/A "usb_bus ptr = 0x%x\n", p_info[pindex].busp);
229N/A found_bus = 1;
229N/A winfo.last_pindex = pindex;
229N/A }
229N/A if (!found_bus) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "could not find a usb_bus pointer \n");
229N/A (void) mutex_unlock(&bus_lock);
229N/A return (FAILURE);
229N/A }
229N/A
229N/A /* Init tmp_usb_busses */
229N/A for (pindex = 0; pindex < winfo.ploaded; pindex ++) {
229N/A if (tmp_usb_busses == NULL) {
229N/A if (p_info[pindex].busp == NULL) {
229N/A continue;
229N/A }
229N/A tmp_usb_busses = p_info[pindex].busp;
229N/A winfo.head_busp = tmp_usb_busses;
229N/A mv_usb_busses = tmp_usb_busses;
229N/A while (mv_usb_busses->next != NULL) {
229N/A mv_usb_busses = mv_usb_busses->next;
229N/A }
229N/A last_usb_busses = mv_usb_busses;
229N/A continue;
229N/A }
229N/A if (p_info[pindex].busp == NULL) {
229N/A continue;
229N/A }
229N/A last_usb_busses->next = p_info[pindex].busp;
229N/A mv_usb_busses = p_info[pindex].busp;
229N/A while (mv_usb_busses->next != NULL) {
229N/A mv_usb_busses = mv_usb_busses->next;
229N/A }
229N/A last_usb_busses = mv_usb_busses;
229N/A }
229N/A usb_busses = winfo.head_busp;
229N/A dump_busses();
229N/A (void) mutex_unlock(&bus_lock);
229N/A
229N/A return (ret_bus);
229N/A}
229N/A
229N/Astruct usb_dev_handle *
229N/Ausb_open(struct usb_device *device)
229N/A{
229N/A int pindex;
229N/A struct usb_dev_handle *dev;
229N/A struct usb_dev_handle *(*hdl)(struct usb_device *);
229N/A char *func = "usb_open";
229N/A
229N/A usb_dprintf(DEBUG_DETAILED, "usb_open: device ptr is 0x%x\n", device);
229N/A if (winfo.active_index == -1) {
229N/A usb_dprintf(DEBUG_DETAILED, "usb_open: active_index = -1 \n");
229N/A pindex = get_index_devicep(device);
229N/A /* could not find this device pointer */
229N/A if (pindex < 0) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "%s: could not map device pointer to bus\n", func);
229N/A return (NULL);
229N/A }
229N/A } else {
229N/A usb_dprintf(DEBUG_FUNCTIONS,
229N/A "usb_open: pindex = %d\n", winfo.active_index);
229N/A pindex = winfo.active_index;
229N/A }
229N/A if (check_sym_hdl(pindex, USB_OPEN) < 0) {
229N/A usb_dprintf(DEBUG_ERRORS, "%s: Symbol not found \n", func);
229N/A return (NULL);
229N/A }
229N/A hdl = USB_OPEN_CAST(p_info[pindex].sym_hdl[USB_OPEN]);
229N/A dev = (*hdl)(device);
229N/A if (usb_add_dev(dev, device, pindex) == SUCCESS) {
229N/A return (dev);
229N/A } else {
229N/A usb_dprintf(DEBUG_ERRORS, "%s:No Memory to add device\n", func);
229N/A return (NULL);
229N/A }
229N/A}
229N/A
229N/Aint
229N/Ausb_close(usb_dev_handle *dev)
229N/A{
229N/A int pindex;
229N/A int ret;
229N/A char *func = "usb_close";
229N/A int (*hdl)(usb_dev_handle *);
229N/A
229N/A pindex = get_pindex(dev, func);
229N/A if (pindex < 0) {
229N/A return (pindex);
229N/A }
229N/A if (check_sym_hdl(pindex, USB_CLOSE) < 0) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "could not find symbol for %s\n", func);
229N/A return (FAILURE);
229N/A }
229N/A hdl = USB_CLOSE_CAST(p_info[pindex].sym_hdl[USB_CLOSE]);
229N/A usb_del_dev(dev, pindex);
229N/A ret = (*hdl)(dev);
229N/A
229N/A return (ret);
229N/A}
229N/A
229N/Aint
229N/Ausb_get_string(usb_dev_handle *dev, int index, int langid, char *buf,
229N/A size_t buflen)
229N/A{
229N/A char *func = "usb_get_string";
229N/A int (*hdl)(usb_dev_handle *, int, int, char *, size_t);
229N/A
229N/A if ((hdl = USB_GET_STRING_CAST
229N/A (lookup_sym_hdl(dev, USB_GET_STRING, func))) == NULL) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "could not find symbol for %s\n", func);
229N/A return (-ENOTSUP);
229N/A }
229N/A
229N/A return ((*hdl)(dev, index, langid, buf, buflen));
229N/A}
229N/A
229N/Aint
229N/Ausb_get_string_simple(usb_dev_handle *dev, int index, char *buf,
229N/A size_t buflen)
229N/A{
229N/A char *func = "usb_get_string_simple";
229N/A int (*hdl)(usb_dev_handle *, int, char *, size_t);
229N/A
229N/A if ((hdl = USB_GET_STRING_SIMPLE_CAST
229N/A (lookup_sym_hdl(dev, USB_GET_STRING_SIMPLE, func))) == NULL) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "could not find symbol for %s\n", func);
229N/A return (-ENOTSUP);
229N/A }
229N/A
229N/A return ((*hdl)(dev, index, buf, buflen));
229N/A}
229N/A
229N/Aint
229N/Ausb_get_descriptor_by_endpoint(usb_dev_handle *dev, int ep,
229N/A unsigned char type, unsigned char index, void *buf, int size)
229N/A{
229N/A char *func = "usb_get_descriptor_by_endpoint";
229N/A int (*hdl)(usb_dev_handle *, int, unsigned char,
229N/A unsigned char, void *, int);
229N/A
229N/A if ((hdl = USB_GET_DESCRIPTOR_BY_ENDPOINT_CAST
229N/A (lookup_sym_hdl(dev, USB_GET_DESCRIPTOR_BY_ENDPOINT, func)))
229N/A == NULL) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "could not find symbol for %s\n", func);
229N/A return (-ENOTSUP);
229N/A }
229N/A
229N/A return ((*hdl)(dev, ep, type, index, buf, size));
229N/A}
229N/A
229N/Aint
229N/Ausb_get_descriptor(usb_dev_handle *dev, unsigned char type,
229N/A unsigned char index, void *buf, int size)
229N/A{
229N/A char *func = "usb_get_descriptor";
229N/A int (*hdl)(usb_dev_handle *, unsigned char,
229N/A unsigned char, void *, int);
229N/A
229N/A if ((hdl = USB_GET_DESCRIPTOR_CAST
229N/A (lookup_sym_hdl(dev, USB_GET_DESCRIPTOR, func))) == NULL) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "could not find symbol for %s\n", func);
229N/A return (-ENOTSUP);
229N/A }
229N/A
229N/A return ((*hdl)(dev, type, index, buf, size));
229N/A}
229N/A
229N/Aint
229N/Ausb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout)
229N/A{
229N/A char *func = "usb_bulk_write";
229N/A int (*hdl)(usb_dev_handle *, int, char *, int, int);
229N/A
229N/A if ((hdl = USB_BULK_WRITE_CAST
229N/A (lookup_sym_hdl(dev, USB_BULK_WRITE, func))) == NULL) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "could not find symbol for %s\n", func);
229N/A return (-ENOTSUP);
229N/A }
229N/A return (*hdl)(dev, ep, bytes, size, timeout);
229N/A}
229N/A
229N/Aint
229N/Ausb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout)
229N/A{
229N/A char *func = "usb_bulk_read";
229N/A int (*hdl)(usb_dev_handle *, int, char *, int, int);
229N/A
229N/A if ((hdl = USB_BULK_READ_CAST
229N/A (lookup_sym_hdl(dev, USB_BULK_READ, func))) == NULL) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "could not find symbol for %s\n", func);
229N/A return (-ENOTSUP);
229N/A }
229N/A
229N/A return ((*hdl)(dev, ep, bytes, size, timeout));
229N/A}
229N/A
229N/Aint
229N/Ausb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes,
229N/A int size, int timeout)
229N/A{
229N/A char *func = "usb_interrupt_read";
229N/A int (*hdl)(usb_dev_handle *, int, char *, int, int);
229N/A
229N/A if ((hdl = USB_INTERRUPT_READ_CAST
229N/A (lookup_sym_hdl(dev, USB_INTERRUPT_READ, func))) == NULL) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "could not find symbol for %s\n", func);
229N/A return (-ENOTSUP);
229N/A }
229N/A
229N/A return ((*hdl)(dev, ep, bytes, size, timeout));
229N/A}
229N/A
229N/Aint
229N/Ausb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes,
229N/A int size, int timeout)
229N/A{
229N/A char *func = "usb_interrupt_write";
229N/A int (*hdl)(usb_dev_handle *, int, char *, int, int);
229N/A
229N/A if ((hdl = USB_INTERRUPT_WRITE_CAST
229N/A (lookup_sym_hdl(dev, USB_INTERRUPT_WRITE, func))) == NULL) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "could not find symbol for %s\n", func);
229N/A return (-ENOTSUP);
229N/A }
229N/A
229N/A return ((*hdl)(dev, ep, bytes, size, timeout));
229N/A}
229N/A
229N/Aint
229N/Ausb_control_msg(usb_dev_handle *dev, int requesttype, int request,
229N/A int value, int index, char *bytes, int size, int timeout)
229N/A{
229N/A char *func = "usb_control_msg";
229N/A int (*hdl)(usb_dev_handle *, int, int, int, int, char *, int, int);
229N/A
229N/A if ((hdl = USB_CONTROL_MSG_CAST
229N/A (lookup_sym_hdl(dev, USB_CONTROL_MSG, func))) == NULL) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "could not find symbol for %s\n", func);
229N/A return (-ENOTSUP);
229N/A }
229N/A
229N/A return ((*hdl)(dev, requesttype, request, value, index,
229N/A bytes, size, timeout));
229N/A}
229N/A
229N/Aint
229N/Ausb_set_configuration(usb_dev_handle *dev, int configuration)
229N/A{
229N/A char *func = "usb_set_configuration";
229N/A int (*hdl)(usb_dev_handle *, int);
229N/A
229N/A if ((hdl = USB_SET_CONFIGURATION_CAST
229N/A (lookup_sym_hdl(dev, USB_SET_CONFIGURATION, func))) == NULL) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "could not find symbol for %s\n", func);
229N/A return (-ENOTSUP);
229N/A }
229N/A
229N/A return ((*hdl)(dev, configuration));
229N/A}
229N/A
229N/Aint
229N/Ausb_claim_interface(usb_dev_handle *dev, int interface)
229N/A{
229N/A char *func = "usb_claim_interface";
229N/A int (*hdl)(usb_dev_handle *, int);
229N/A
229N/A if ((hdl = USB_CLAIM_INTERFACE_CAST
229N/A (lookup_sym_hdl(dev, USB_CLAIM_INTERFACE, func))) == NULL) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "could not find symbol for %s\n", func);
229N/A return (-ENOTSUP);
229N/A }
229N/A
229N/A return ((*hdl)(dev, interface));
229N/A}
229N/A
229N/Aint
229N/Ausb_release_interface(usb_dev_handle *dev, int interface)
229N/A{
229N/A char *func = "usb_release_interface";
229N/A int (*hdl)(usb_dev_handle *, int);
229N/A
229N/A if ((hdl = USB_RELEASE_INTERFACE_CAST
229N/A (lookup_sym_hdl(dev, USB_RELEASE_INTERFACE, func))) == NULL) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "could not find symbol for %s\n", func);
229N/A return (-ENOTSUP);
229N/A }
229N/A
229N/A return ((*hdl)(dev, interface));
229N/A}
229N/A
229N/Aint
229N/Ausb_set_altinterface(usb_dev_handle *dev, int alternate)
229N/A{
229N/A char *func = "usb_set_altinterface";
229N/A int (*hdl)(usb_dev_handle *, int);
229N/A
229N/A if ((hdl = USB_SET_ALTINTERFACE_CAST
229N/A (lookup_sym_hdl(dev, USB_SET_ALTINTERFACE, func))) == NULL) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "could not find symbol for %s\n", func);
229N/A return (-ENOTSUP);
229N/A }
229N/A
229N/A return ((*hdl)(dev, alternate));
229N/A}
229N/A
229N/Aint
229N/Ausb_resetep(usb_dev_handle *dev, unsigned int ep)
229N/A{
229N/A char *func = "usb_resetep";
229N/A int (*hdl)(usb_dev_handle *, unsigned int);
229N/A
229N/A if ((hdl = USB_RESETEP_CAST
229N/A (lookup_sym_hdl(dev, USB_RESETEP, func))) == NULL) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "could not find symbol for %s\n", func);
229N/A return (-ENOTSUP);
229N/A }
229N/A
229N/A return ((*hdl)(dev, ep));
229N/A}
229N/A
229N/Aint
229N/Ausb_clear_halt(usb_dev_handle *dev, unsigned int ep)
229N/A{
229N/A
229N/A char *func = "usb_clear_halt";
229N/A int (*hdl)(usb_dev_handle *, unsigned int);
229N/A
229N/A if ((hdl = USB_CLEAR_HALT_CAST
229N/A (lookup_sym_hdl(dev, USB_CLEAR_HALT, func))) == NULL) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "could not find symbol for %s\n", func);
229N/A return (-ENOTSUP);
229N/A }
229N/A
229N/A return ((*hdl)(dev, ep));
229N/A}
229N/A
229N/Aint
229N/Ausb_reset(usb_dev_handle *dev)
229N/A{
229N/A char *func = "usb_reset";
229N/A int (*hdl)(usb_dev_handle *);
229N/A
229N/A if ((hdl = USB_RESET_CAST
229N/A (lookup_sym_hdl(dev, USB_RESET, func))) == NULL) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "could not find symbol for %s\n", func);
229N/A return (-ENOTSUP);
229N/A }
229N/A return ((*hdl)(dev));
229N/A}
229N/A
229N/Aint
229N/Ausb_find_devices(void)
229N/A{
229N/A int pindex;
229N/A int (*hdl_usb_find_devices)(void);
229N/A int ret_val = 0;
229N/A int err_store = 0;
229N/A
229N/A /*
229N/A * devices can go away here.
229N/A * devices can get added also.
229N/A * the dev handles list does not update it only updates
229N/A * for usb_close and usb_open
229N/A */
229N/A for (pindex = 0; pindex < winfo.ploaded; pindex ++) {
229N/A if (check_sym_hdl(pindex, USB_FIND_DEVICES) < 0) {
229N/A continue;
229N/A }
229N/A hdl_usb_find_devices = USB_FIND_DEVICES_CAST
229N/A (p_info[pindex].sym_hdl[USB_FIND_DEVICES]);
229N/A ret_val = (*hdl_usb_find_devices)();
229N/A if (ret_val < 0) {
229N/A err_store = ret_val;
229N/A } else {
229N/A ret_val += ret_val;
229N/A }
229N/A }
229N/A if (!err_store) {
229N/A return (ret_val);
229N/A } else {
229N/A /* return any error for multiple busses */
229N/A return (err_store);
229N/A }
229N/A}
229N/A
229N/Astruct usb_device *
229N/Ausb_device(usb_dev_handle *dev)
229N/A{
229N/A char *func = "usb_device";
229N/A struct usb_device *((*hdl)(usb_dev_handle *));
229N/A
229N/A if ((hdl = USB_DEVICE_CAST
229N/A (lookup_sym_hdl(dev, USB_DEVICE, func))) == NULL) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "could not find symbol for %s\n", func);
229N/A return (NULL);
229N/A }
229N/A
229N/A return ((*hdl)(dev));
229N/A}
229N/A
229N/A/*
229N/A * This returns the wrapper's usb_busses pointer not the plugins
229N/A */
229N/Astruct usb_bus *
229N/Ausb_get_busses(void)
229N/A{
229N/A return (usb_busses);
229N/A}
229N/A
229N/A/*
229N/A * Makes sense to only return a single
229N/A * str error - so using the strerror of the
229N/A * last plugin that was used
229N/A */
229N/A
229N/Achar *
229N/Ausb_strerror(void)
229N/A{
229N/A int pindex;
229N/A char *func = "usb_strerror";
229N/A char *(*hdl_usb_strerror)(void);
229N/A
229N/A /*
229N/A * usb_strerror is only of interest for the last
229N/A * call to the plugin. So call it for the last
229N/A * plugin used
229N/A */
229N/A for (pindex = 0; pindex < winfo.ploaded; pindex ++) {
229N/A if (check_sym_hdl(pindex, USB_STRERROR) < 0) {
229N/A usb_dprintf(DEBUG_ERRORS,
229N/A "could not find symbol for %s\n", func);
229N/A continue;
229N/A }
229N/A if (pindex == winfo.last_pindex) {
229N/A hdl_usb_strerror = USB_STRERROR_CAST
229N/A (p_info[pindex].sym_hdl[USB_STRERROR]);
229N/A return ((*hdl_usb_strerror)());
229N/A }
229N/A }
229N/A
229N/A return (NULL);
229N/A}
229N/A
229N/Astatic void
229N/Ausb_dprintf(int level, char *format, ...)
229N/A{
229N/A va_list ap;
229N/A char buf[512];
229N/A
229N/A va_start(ap, format);
229N/A (void) vsnprintf(buf, sizeof (buf), format, ap);
229N/A if (libusb_debug >= level) {
229N/A (void) fprintf(stderr, buf);
229N/A }
229N/A va_end(ap);
229N/A}