wr_libusb.c revision 229
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 * See the License for the specific language governing permissions 229N/A * and limitations under the License. 229N/A * When distributing Covered Code, include this CDDL HEADER in each 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 * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. 229N/A * libusb wrapper library 229N/A * Implements the libusb specification and calls into platform dependent 229N/A * library implementations of sunray and solaris. 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 * 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 * 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 * 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 * Loads all the symbols of the plugins and maps apps calls -> plugin 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 * 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 * Construct the plugin directory 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 /* skip . and .. entries */ 229N/A * Ignore files that are not *.so.X 229N/A "did not load %s:%s\n",
229N/A * using PATH_MAX len here 229N/A "pathname > PATH_MAX %s",
229N/A /* go on to try read next module */ 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 /* end of dir stream */ 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 * 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 "Failed to load libusb plugins \n");
229N/A * Will load at most MAX_PLUGINS 229N/A /* reached the end of modules read into the array */ 229N/A /* just try to load the next one */ 229N/A "symbols for plugin %s\n",
229N/A /* try the next plugin */ 229N/A /* ploaded is the highest index that had a module entry */ 229N/A * For debugging of bus pointers 229N/A * Used to unload plugin 229N/A /* call the plugins libusb_fini here */ 229N/A "hdl_libusb_fini is NULL \n");
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 * 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 * This is needed simply because we want to able 229N/A * to map the device handles to the plugin module 229N/A /* first device handle to be added */ 229N/A "Error adding device to list \n");
229N/A /* curr_devh points to last devh handle */ 229N/A "Error adding device to list \n");
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 /* Not the last dev hdl */ 229N/A "d_dev->next != NULL\n");
229N/A /* Not the first dev hdl */ 229N/A "d_dev->prev != NULL\n");
229N/A * first dev hdl on list 229N/A * if only handle then point to NULL 229N/A "d_dev->next != NULL\n");
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 * returns a valid symbol handle or NULL 229N/A /* this is needed to support strerror() of last call */ 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 "devicep: pindex = %d\n",
229N/A /* can have a valid handle but a null prefix */ 229N/A "could not alloc space for prefix\n");
229N/A * Used to form prefixed interface symbols for plugins 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 * 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 * usb_init() entry point: 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 * If usb_init() already called then do not reinit 229N/A "%s: could not load plugin modules\n",
func);
229N/A /* condition for libusb_init not implemented */ 229N/A "hdl_libusb_init is NULL \n");
229N/A "%s: libusb_init() returned %d\n",
229N/A /* first plugin to set exclusive */ 229N/A "value for libusb_init\n");
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 "No Version number for plugin found \n");
229N/A "version string exceeds max" 229N/A "characters, truncating\n");
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 "plugin version %s not supported\n",
229N/A /* env debug variables override completely what the app sets */ 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 * ret_bus is supposed to be the number of busses changed 229N/A /* calling the find_busses whose symbols can be found */ 229N/A * updated usb_busses pointer for the plugins 229N/A "could not find a usb_bus pointer \n");
229N/A /* Init tmp_usb_busses */ 229N/A /* could not find this device pointer */ 229N/A "%s: could not map device pointer to bus\n",
func);
229N/A char *
func =
"usb_get_descriptor_by_endpoint";
229N/A unsigned char,
void *,
int);
229N/A unsigned char,
void *,
int);
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 /* return any error for multiple busses */ 229N/A * This returns the wrapper's usb_busses pointer not the plugins 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 * usb_strerror is only of interest for the last 229N/A * call to the plugin. So call it for the last