[svn-commits] tzafrir: branch tools/2.5 r10355 - in /tools/branches/2.5/xpp: ./ xtalk/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Nov 30 04:25:19 CST 2011


Author: tzafrir
Date: Wed Nov 30 04:25:16 2011
New Revision: 10355

URL: http://svnview.digium.com/svn/dahdi?view=rev&rev=10355
Log:
xpp: Serialized Parallel load; E-Main-3 firmware

This introduces support for loading multiple firmwares in parallel also
for the case of a manual load. This is anyway the case for an automatic
load from udev.

* libusb needs to scan the bus all too often. This causes occasional
  failures for opening devices.
* Thus introduce a semaphore to serialize uses of libusb.

E-Main-3 firmware differs by a different value of bcdDevice:

* Read this from the sysfs devices tree.
* Fall back to lsusb -v (much slower) is sysfs not available.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen at xorcom.com>

Modified:
    tools/branches/2.5/xpp/xpp_fxloader
    tools/branches/2.5/xpp/xtalk/xusb.c

Modified: tools/branches/2.5/xpp/xpp_fxloader
URL: http://svnview.digium.com/svn/dahdi/tools/branches/2.5/xpp/xpp_fxloader?view=diff&rev=10355&r1=10354&r2=10355
==============================================================================
--- tools/branches/2.5/xpp/xpp_fxloader (original)
+++ tools/branches/2.5/xpp/xpp_fxloader Wed Nov 30 04:25:16 2011
@@ -69,9 +69,6 @@
 ASTRIBANK_TOOL=${ASTRIBANK_TOOL:-/usr/sbin/astribank_tool}
 XPP_CONFIG="${XPP_CONFIG:-/etc/dahdi/xpp.conf}"
 XPP_UDEV_SLEEP_TIME="${XPP_UDEV_SLEEP_TIME:-15}"
-
-USB_FW="${USB_FW:-USB_FW.hex}"
-USB_RECOV="${USB_RECOV:-USB_RECOV.hex}"
 
 if [ -r "$DEFAULTS" ]; then
 	. "$DEFAULTS"
@@ -113,6 +110,132 @@
   fi
 }
 
+list_via_proc() {
+	cat /proc/bus/usb/devices | egrep '^P:|^T:' | sed \
+		-e '/^T:/s/ *Spd.*//' \
+		-e '/^T:/s, *Lev.*Dev#= *,\t,' \
+		-e '/^T:/s,Bus=,,' \
+		-e '/^P:/s,[A-Za-z]\+=,,g' \
+		-e '/^P:/s,\.,,g' | awk -vusb_prefix="$USB_PREFIX" '
+			/^T:/	{
+				bus=$2
+				dev=$3
+			}
+			/^P:/	{
+				vendor=$2
+				sub("0x", "", vendor);
+				prod=$3
+				sub("0x", "", product);
+				bcd=$4
+				printf("%4s/%4s/%d\t%s/%03d/%03d\n",
+					vendor, prod, bcd, usb_prefix, bus, dev);
+			}
+			'
+}
+
+list_via_sysfs() {
+	find /sys/bus/usb/devices -maxdepth 1 -mindepth 1 | \
+		egrep -v '/usb[0-9]|:' | while read dev; do
+			(
+				cat "$dev/idVendor"
+				cat "$dev/idProduct"
+				cat "$dev/bcdDevice"
+				echo "$dev" | sed \
+					-e 's,/sys/bus/usb/devices/,,' \
+					-e 's,-.*,,'
+				cat "$dev/devnum"
+			) | tr -s '\n' '\t'
+			echo ''
+		done | awk -vusb_prefix="$USB_PREFIX" '{
+			printf("%4s/%4s/%d\t%s/%03d/%03d\n",
+				$1, $2, $3, usb_prefix, $4, $5);
+			}'
+}
+
+list_via_lsusb() {
+	lsusb -v | awk -vusb_prefix="$USB_PREFIX" '
+		/^Bus/ {
+			sub(":", "", $4);
+			dev = sprintf("%s/%s/%s ", usb_prefix, $2, $4);
+		}
+		/idVendor/  {
+			id_vendor = $2
+			sub("0x", "", id_vendor);
+		}
+		/idProduct/ {
+			id_product = $2
+			sub("0x", "", id_product);
+		}
+		/bcdDevice/ {
+			bcd_device = $2
+			sub("^0*", "", bcd_device);
+			sub("[.]", "", bcd_device);
+			printf("%s/%s/%s\t%s\n",
+				id_vendor, id_product, bcd_device, dev);
+		}
+		'
+}
+
+list_devs() {
+	#echo >&2 "list_devs"
+	if [ "$#" -eq 0 ]; then
+		if [ -f /proc/bus/usb/devices ]; then
+			method='via_proc'
+		elif [ -d /sys/bus/usb/devices ]; then
+			method='via_sysfs'
+		else
+			method='via_lsusb'
+		fi
+	elif [ "$#" -eq 1 ]; then
+		method="$1"
+	else
+		echo >&2 "$0: unknown list_devs method='$method'"
+		exit 1
+	fi
+
+	case "$method" in
+	via_proc|via_sysfs|via_lsusb)
+		;;
+	*)
+		echo >&2 "$0: unknown list_devs method='$method'"
+		exit 1
+		;;
+	esac
+	list_$method | grep -v '^0000/0000/' | sort
+}
+
+filter_devs() {
+	id_str="$1"
+
+	#echo >&2 "filter_devs($id_str)"
+	list_devs | awk -vid_str="$id_str" '{ if ($1 ~ id_str) { print } }'
+}
+
+usb_firmware_device() {
+	id_str="$1"
+	devpath="$2"
+
+	case "$id_str" in
+	e4e4/11[3456]0/101|e4e4/1163/101)
+		fw="USB_FW.hex"
+		;;
+	e4e4/116[03]/201)
+		fw="USB_FW.201.hex"
+		;;
+	e4e4/*)
+		debug "No USB firmware for device $devpath ($id_str)"
+		return
+		;;
+	*)
+		return
+		;;
+	esac
+	fw_file="$FIRMWARE_DIR/$fw"
+	ver=$(awk '/\$Id:/ { print $4 }' $fw_file)
+	debug "USB Firmware $fw_file (Version=$ver) into $devpath"
+	run_fxload -D "$devpath" -I "$fw_file" || exit 1
+}
+
 run_astribank_hexload() {
 	debug "Running: $ASTRIBANK_HEXLOAD $*"
 	$ASTRIBANK_HEXLOAD "$@" | $LOGGER
@@ -133,18 +256,14 @@
 	fi
 }
 
-load_usb_fw() {
-  v_id=$1
-  p_id=$2
-  fw=$3
-  
-  devices=`find_dev $v_id $p_id`
-  for dev in $devices
-  do
-    ver=$(awk '/\$Id:/ { print $4 }' $FIRMWARE_DIR/$fw)
-    debug "USB Firmware $FIRMWARE_DIR/$fw (Version=$ver) into $dev"
-    run_fxload -D $dev -I $FIRMWARE_DIR/$fw || exit 1
-  done
+usb_firmware_all_devices() {
+	devs=`list_devs`
+	echo "USB firmware"
+	echo "$devs" | while read id_str devpath
+	do
+		usb_firmware_device "$id_str" "$devpath"
+	done
+	wait_renumeration $numdevs 'e4e4/11[3456]1/*' "usb_firmware_all_devices"
 }
 
 load_fw_device() {
@@ -152,16 +271,17 @@
 	fw="$2"
 	debug "FPGA loading $fw into $dev"
 	run_astribank_hexload -D "$dev" -F "$FIRMWARE_DIR/$fw"
-	if [ "$fw" = "FPGA_1161.hex" ]; then
+	case "$fw" in
+	FPGA_1161*.hex)
 	        echo_file="$FIRMWARE_DIR/OCT6104E-256D.ima"
 		law=''
 		law_str='uLaw'
-		abtool_output=`$ASTRIBANK_TOOL -D "$dev" -Q 2>/dev/null`
-		card_type=`echo "$abtool_output" | grep '^CARD 4:' |  cut -d= -f2 | cut -d. -f1`
-		if [ "$card_type" = '5' ]; then
+		card_type=`run_astribank_tool -D "$dev" -Q 2>&1 | grep 'CARD 4' | sed -e 's/.*type=//' -e 's/\..*//'`
+		caps_num=`run_astribank_tool -D "$dev" -Q 2>&1 | grep 'ECHO ports' | sed -e 's/.*: *//'`
+		if [ $card_type -eq 5 ]; then
 			debug "ECHO burning into $dev: $echo_file"
-			card_type_first=`echo "$abtool_output" | grep '^CARD 0:' |  cut -d= -f2 | cut -d. -f1`
-			case "$card_type_first" in
+			card_type=`run_astribank_tool -D "$dev" -Q 2>&1 | grep 'CARD 0' | sed -e 's/.*type=//' -e 's/\..*//'`
+			case "$card_type" in
 			3) 	law="-A";;
 			4)
 				pri_protocol=''
@@ -182,88 +302,116 @@
 			if [ "$caps_num" != '0' ]; then
 				run_astribank_hexload -D "$dev" -O $law "$echo_file"
 			else
-				$LOGGER "WARNING: ECHO burning was skipped (no capabilities)"
+				echo "WARNING: ECHO burning was skipped (no capabilities)"
 			fi
 		fi
 		pic_files=`echo "$FIRMWARE_DIR"/PIC_TYPE_[1-4].hex`
-		debug "PIC burning into $dev: $pic_files"
+		debug "PIC burning into $dev: begin $pic_files"
 		run_astribank_hexload -D "$dev" -p $pic_files
-		debug "PIC burning finished $pic_files"
-	fi
+		debug "PIC burning into $dev: end $pic_files"
+		;;
+	esac
 	# Do renumeration!
-	run_astribank_tool -D "$dev" -n > /dev/null
-	debug "Reenumeration done."
-}
-
-#
-# Use in manual loading. Parallelize loading
-# firmwares to all of our devices
-#
-firmware_by_id() {
-  v_id=$1
-  p_id=$2
-  fw=$3
-  
-  devices=`find_dev $v_id $p_id`
-  childs=""
-  for dev in $devices
-  do
-	(
-	set -e
-
-	load_fw_device "$dev" "$fw"
+	run_astribank_tool -D "$dev" -n > /dev/null 2>&1
+	debug "Renumeration of $dev done."
+}
+
+fpga_firmware_device() {
+	id_str="$1"
+	devpath="$2"
+
+	id_product=`echo "$id_str" | cut -d/ -f2`
+	bcd_device=`echo "$id_str" | cut -d/ -f3`
+	case "$id_str" in
+	e4e4/1131/101)
+		fw="FPGA_FXS.hex"
+		;;
+	e4e4/11[456]1/101)
+		fw="FPGA_${id_product}.hex"
+		;;
+	e4e4/1161/201)
+		fw="FPGA_${id_product}.${bcd_device}.hex"
+		;;
+	e4e4/*)
+		debug "No FPGA firmware for device $devpath ($id_str)"
+		return
+		;;
+	*)
+		return
+		;;
+	esac
+	debug "Loading $fw into $devpath"
+	load_fw_device "$devpath" "$fw"
 	sleep_if_race
-	) &
-	childs="$childs $!"
-	sleep 0.4
-  done
-  # Wait for specific childs to get their exit status
-  wait $childs
 }
 
 numdevs() {
-  v_ids="$1"
-  p_ids="$2"
-
-  for v in $v_ids
-  do
-    (
-      for p in $p_ids
-      do
-        find_dev $v $p
-      done
-    )
-  done | wc -w
+	id_str="$1"
+
+	#echo >&2 "numdevs($id_str)"
+	filter_devs "$id_str" | wc -l
 }
 
 wait_renumeration() {
-  num="$1"
-  v_ids="$2"
-  p_ids="$3"
-
-  while
-    n=`numdevs "$v_ids" "$p_ids"`
-    [ "$num" -gt "$n" ]
-  do
-    echo -n "."
-    sleep 1
-  done
-  echo "Got all $num devices"
+	num="$1"
+	id_str="$2"
+	caller="$3"
+	iter=10
+
+	prev=0
+	echo "Waiting renumeration ($caller)"
+	while
+		n=`numdevs "$id_str"`
+		[ "$num" -gt "$n" ]
+	do
+		if [ "$prev" -lt "$n" ]; then
+			echo -n "+"
+		else
+			echo -n "."
+		fi
+		sleep 1
+		prev="$n"
+		debug "wait($iter) (found $n from $num devices) ($caller)"
+		if ! iter=`expr $iter - 1`; then
+			echo "Timeout (found $n from $num devices) ($caller)"
+			break;
+		fi
+	done
+	echo "Got all $num devices ($caller)"
+	sleep 1	# Let everything settle
+}
+
+fpga_firmware_all_devices() {
+	echo "Loading FPGA firmwares" | $LOGGER
+	devs=`filter_devs 'e4e4/11[3456]1/*'`
+	n=`echo "$devs" | wc -l`
+	echo "$devs" | (
+		while read id_str devpath; do
+			fpga_firmware_device "$id_str" "$devpath" &
+		done
+		sleep 1
+		echo "Wait for FPGA loading processes"
+		wait
+		) 2>&1 | $LOGGER
+	wait_renumeration $numdevs 'e4e4/11[3456]2/*' "fpga_firmware_device"
 }
 
 reset_fpga() {
-  totaldevs=`numdevs e4e4 '11[3456][0123]'`
-  devices=`find_dev e4e4 '11[3456][12]'`
-  debug "Reseting devices [$totaldevs devices]"
-  for dev in $devices
-  do
-	debug "Resetting FPGA Firmware on $dev"
-	sleep_if_race
-	run_astribank_tool -D "$dev" -r full 2>&1 >/dev/null
-  done
-  if [ "$1" = 'wait' ]; then
-	  wait_renumeration $totaldevs e4e4 '11[3456][03]'
-  fi
+	devices=`filter_devs 'e4e4/11[3456][124]/*'`
+	totaldevs=`numdevs 'e4e4/11[3456][124]/*'`
+	$LOGGER -- "Reseting devices [$totaldevs devices]"
+	echo "$devices" | grep -v '^$' | while read id_str dev
+	do
+		(
+			debug "Resetting FPGA Firmware on $dev"
+			sleep_if_race
+			run_astribank_tool -D "$dev" -r full >/dev/null 2>&1
+		) &
+	done
+	wait
+	if [ "$1" = 'wait' ]; then
+		wait_renumeration $totaldevs 'e4e4/11[3456][03]/*' "reset_fpga"
+	fi
 }
 
 usage() {
@@ -304,26 +452,20 @@
 reset)
 	reset_fpga
 	;;
+list)
+	filter_devs 'e4e4/*/*'
+	exit 0
+	;;
 xppdetect|load|usb)
-	numdevs=`numdevs e4e4 '11[3456][013]'`
+	numdevs=`numdevs 'e4e4/11[3456][0134]/*'`
 	$LOGGER -- "--------- FIRMWARE LOADING: ($1) [$numdevs devices]"
 
-	load_usb_fw e4e4 1130 $USB_FW
-	load_usb_fw e4e4 1140 $USB_FW
-	load_usb_fw e4e4 1150 $USB_FW
-	load_usb_fw e4e4 1160 $USB_FW
-	load_usb_fw e4e4 1163 $USB_FW
-	wait_renumeration $numdevs e4e4 '11[3456]1'
+	usb_firmware_all_devices 2>&1 | $LOGGER
 	if [ "$1" != 'usb' ]
 	then
-		firmware_by_id e4e4 1131 FPGA_FXS.hex
-		firmware_by_id e4e4 1141 FPGA_1141.hex
-		firmware_by_id e4e4 1151 FPGA_1151.hex
-		firmware_by_id e4e4 1161 FPGA_1161.hex
-		wait_renumeration $numdevs e4e4 '11[3456]2'
-	fi
-
-	sleep 3		# Let it stabilize
+		fpga_firmware_all_devices
+	fi
+
 	$LOGGER -- "--------- FIRMWARE IS LOADED"
 	exit 0
 	;;
@@ -379,27 +521,17 @@
 	fi
 
 	$LOGGER "Trying to find what to do for product $PRODUCT, device $DEVICE"
-	prod_id=`echo "$PRODUCT" | cut -d/ -f2`
 	case "$PRODUCT" in
 	e4e4/11[3456]0/*|e4e4/1163/*)
-		FIRM_USB="$FIRMWARE_DIR/$USB_FW"
-		$LOGGER "Loading firmware '$FIRM_USB' into '$DEVICE'"
-		run_fxload -D "$DEVICE" -I "$FIRM_USB"
+		usb_firmware_device "$PRODUCT" "$DEVICE"
 		;;
 	e4e4/11[3456]1/*)
-		# There are potentially two separate udev events, for
-		# each of the two endpoints. Ignore the first interface:
-		case "$DEVPATH" in *.0) exit 0;; esac
-		if [ "$prod_id" = 1131 ]; then
-			FIRM_FPGA="FPGA_FXS.hex"	# Legacy
-		else
-			FIRM_FPGA="FPGA_$prod_id.hex"
-		fi
 		sleep_if_race
-		load_fw_device "$DEVICE" "$FIRM_FPGA"
+		fpga_firmware_device "$PRODUCT" "$DEVICE" &
+		wait	# parallel firmware loading
 		;;
 	esac	
 }
 
-udev_delayed_load &
-
+udev_delayed_load 2>&1 | $LOGGER &
+

Modified: tools/branches/2.5/xpp/xtalk/xusb.c
URL: http://svnview.digium.com/svn/dahdi/tools/branches/2.5/xpp/xtalk/xusb.c?view=diff&rev=10355&r1=10354&r2=10355
==============================================================================
--- tools/branches/2.5/xpp/xtalk/xusb.c (original)
+++ tools/branches/2.5/xpp/xtalk/xusb.c Wed Nov 30 04:25:16 2011
@@ -30,11 +30,16 @@
 #include <arpa/inet.h>
 #include <debug.h>
 #include <xusb.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
 
 static const char rcsid[] = "$Id$";
 
 #define	DBG_MASK	0x01
 #define	TIMEOUT	500
+#define	MAX_RETRIES	10
 
 struct xusb {
 	struct usb_device	*dev;
@@ -56,6 +61,8 @@
 	size_t			packet_size;
 };
 
+static void xusb_init();
+
 void xusb_init_spec(struct xusb_spec *spec, char *name,
 		uint16_t vendor_id, uint16_t product_id,
 		int nifaces, int iface, int nep, int ep_out, int ep_in)
@@ -363,9 +370,7 @@
 	struct usb_bus		*bus;
 
 	DBG("\n");
-	usb_init();
-	usb_find_busses();
-	usb_find_devices();
+	xusb_init();
 	for (bus = usb_get_busses(); bus; bus = bus->next) {
 		int			bus_num;
 		char			tmppath[PATH_MAX + 1];
@@ -477,9 +482,7 @@
 		ERR("Failed allocation new xlist");
 		goto fail_xlist;
 	}
-	usb_init();
-	usb_find_busses();
-	usb_find_devices();
+	xusb_init();
 	for (bus = usb_get_busses(); bus; bus = bus->next) {
 		for (dev = bus->devices; dev; dev = dev->next) {
 			struct usb_device_descriptor	*dev_desc;
@@ -540,7 +543,10 @@
 		xusb = curr->data;
 		xlist_destroy(curr, NULL);
 		xlist_destroy(xusb_list, NULL);
-		xusb_claim_interface(xusb);
+		if(!xusb_claim_interface(xusb)) {
+			xusb_destroy(xusb);
+			return NULL;
+		}
 		xusb_showinfo(xusb);
 		break;
 	default:
@@ -657,12 +663,14 @@
 int xusb_send(struct xusb *xusb, char *buf, int len, int timeout)
 {
 	int		ret;
+	int		retries = 0;
 
 	dump_packet(LOG_DEBUG, DBG_MASK, __FUNCTION__, buf, len);
 	if(EP_OUT(xusb) & USB_ENDPOINT_IN) {
 		ERR("%s called with an input endpoint 0x%x\n", __FUNCTION__, EP_OUT(xusb));
 		return -EINVAL;
 	}
+retry_write:
 	ret = usb_bulk_write(xusb->handle, EP_OUT(xusb), buf, len, timeout);
 	if(ret < 0) {
 		/*
@@ -672,17 +680,39 @@
 		if(ret != -ENODEV) {
 			ERR("bulk_write to endpoint 0x%x failed: (%d) %s\n",
 				EP_OUT(xusb), ret, usb_strerror());
-			dump_packet(LOG_ERR, DBG_MASK, "xbus_send[ERR]", buf, len);
+			dump_packet(LOG_ERR, DBG_MASK, "xusb_send[ERR]", buf, len);
 			//exit(2);
 		} else {
 			DBG("bulk_write to endpoint 0x%x got ENODEV\n", EP_OUT(xusb));
 			xusb_close(xusb);
 		}
 		return ret;
-	} else if(ret != len) {
+	}
+	if(!ret) {
+#if 0
+		FILE	*fp;
+
+		fp = fopen("/tmp/xusb.log", "a");
+		if (!fp) {
+			ERR("%s: Failed writing to /tmp/xusb.log\n", __func__);
+			return -EFAULT;
+		}
+		fprintf(fp, "[%ld] bulk_write to endpoint 0x%x short write[%d]: (%d)\n",
+			time(NULL), EP_OUT(xusb), retries, ret);
+		fclose(fp);
+#endif
+		ERR("bulk_write to endpoint 0x%x short write[%d]: (%d)\n",
+			EP_OUT(xusb), retries, ret);
+		if (retries++ > MAX_RETRIES) {
+			return -EFAULT;
+		}
+		usleep(100);
+		goto retry_write;
+	}
+	if(ret != len) {
 		ERR("bulk_write to endpoint 0x%x short write: (%d) %s\n",
 			EP_OUT(xusb), ret, usb_strerror());
-		dump_packet(LOG_ERR, DBG_MASK, "xbus_send[ERR]", buf, len);
+		dump_packet(LOG_ERR, DBG_MASK, "xusb_send[ERR]", buf, len);
 		return -EFAULT;
 	}
 	return ret;
@@ -691,17 +721,40 @@
 int xusb_recv(struct xusb *xusb, char *buf, size_t len, int timeout)
 {
 	int	ret;
+	int	retries = 0;
 
 	if(EP_IN(xusb) & USB_ENDPOINT_OUT) {
 		ERR("%s called with an output endpoint 0x%x\n", __FUNCTION__, EP_IN(xusb));
 		return -EINVAL;
 	}
+retry_read:
 	ret = usb_bulk_read(xusb->handle, EP_IN(xusb), buf, len, timeout);
 	if(ret < 0) {
 		DBG("bulk_read from endpoint 0x%x failed: (%d) %s\n",
 			EP_IN(xusb), ret, usb_strerror());
 		memset(buf, 0, len);
 		return ret;
+	}
+	if(!ret) {
+#if 0
+		FILE	*fp;
+
+		fp = fopen("/tmp/xusb.log", "a");
+		if (!fp) {
+			ERR("%s: Failed writing to /tmp/xusb.log\n", __func__);
+			return -EFAULT;
+		}
+		fprintf(fp, "[%ld] bulk_read from endpoint 0x%x short read[%d]: (%d)\n",
+			time(NULL), EP_IN(xusb), retries, ret);
+		fclose(fp);
+#endif
+		ERR("bulk_read to endpoint 0x%x short read[%d]: (%d)\n",
+			EP_IN(xusb), retries, ret);
+		if (retries++ > MAX_RETRIES) {
+			return -EFAULT;
+		}
+		usleep(100);
+		goto retry_read;
 	}
 	dump_packet(LOG_DEBUG, DBG_MASK, __FUNCTION__, buf, ret);
 	return ret;
@@ -724,3 +777,74 @@
 	}
 	return 0;
 }
+
+/*
+ * Serialize calls to usb_find_busses()/usb_find_devices()
+ */
+
+static const key_t	SEM_KEY = 0x1a2b3c4d;
+static int semid = -1;	/* Failure */
+
+static void xusb_lock_usb()
+{
+	struct sembuf	sembuf;
+
+	while (semid < 0) {
+		/* Maybe it was already created? */
+		semid = semget(SEM_KEY, 1, 0);
+		if (semid < 0) {
+			/* No, let's create ourselves */
+			semid = semget(SEM_KEY, 1, IPC_CREAT | IPC_EXCL | 0644);
+			if (semid < 0) {
+				/* Someone else won the race to create it */
+				if (errno != ENOENT)
+					ERR("%s: semget() failed: %s\n",
+						__func__, strerror(errno));
+				/* Retry */
+				continue;
+			}
+			/* Initialize */
+			if (semctl(semid, 0, SETVAL, 1) < 0)
+				ERR("%s: SETVAL() failed: %s\n",
+					__func__, strerror(errno));
+		}
+	}
+	DBG("%d: LOCKING\n", getpid());
+	sembuf.sem_num = 0;
+	sembuf.sem_op = -1;
+	sembuf.sem_flg = SEM_UNDO;
+	if (semop(semid, &sembuf, 1) < 0) {
+		ERR("%s: semop() failed: %s\n", __func__, strerror(errno));
+	}
+	DBG("%d: LOCKED\n", getpid());
+}
+
+static void xusb_unlock_usb()
+{
+	struct sembuf	sembuf;
+
+	DBG("%d: UNLOCKING\n", getpid());
+	sembuf.sem_num = 0;
+	sembuf.sem_op = 1;
+	sembuf.sem_flg = SEM_UNDO;
+	if (semop(semid, &sembuf, 1) < 0) {
+		ERR("%s: semop() failed: %s\n", __func__, strerror(errno));
+	}
+	DBG("%d: UNLOCKED\n", getpid());
+}
+
+static int		initizalized = 0;
+
+static void xusb_init()
+{
+	if (!initizalized) {
+		if (!getenv("XUSB_NOLOCK"))
+			xusb_lock_usb();
+		usb_init();
+		usb_find_busses();
+		usb_find_devices();
+		initizalized = 1;
+		if (!getenv("XUSB_NOLOCK"))
+			xusb_unlock_usb();
+	}
+}




More information about the svn-commits mailing list