#!/sbin/openrc-run description="Load USBIP kernel modules and run daemon" : ${USBIP_EXEC:=$(which usbip)} : ${USBIP_EXEC_DAEMON:=$(which usbipd)} depend() { provide usbip need sysfs net } LoadKernelModule () { local module=$1 #----------------- result= if [ -z "$(/sbin/lsmod | grep "^$(basename $module)")" ] then local filename=$(find lib/modules/`uname -r`/kernel -type f -name $module.ko -printf '%f\n') if [ -n "$filename" ] then if ! /sbin/modprobe $module then eerror "Cannot load kernel module '$module'." result=failed fi else eerror "Cannot find kernel module '$module'." result=failed fi fi [ -z "$result" ] } IsAvailable () { local bus_or_device=$(echo $1 | tr '[A-Z]' '[a-z]') local host=$2 #----------------- host=${host:+--remote=$host} : ${host:=--local} $USBIP_EXEC list --parsable $host | sed -n 's|.*busid='$bus_or_device'#.*|yes|p; \ s|.*usbid='$bus_or_device'#.*|yes|p' } GetBus () { local device=$(echo $1 | tr '[A-Z]' '[a-z]') local host=$2 #----------------- host=${host:+--remote=$host} : ${host:=--local} case "$host" in "--remote"*) # FIXME: USBIP bug causing remote devices not to be listed parsable $USBIP_EXEC list --parsable $host | sed -n 's|^[ \t]*\([0-9][0-9]*-[0-9][0-9]*\):.*('"$device"').*|\1|p';; *) $USBIP_EXEC list --parsable $host | sed -n 's|.*busid=\([0-9][0-9]*-[0-9][0-9]*\)#usbid='"$device"'#.*|\1|p';; esac } ExecuteUsbip() { local command=$1 local bus=$2 local host=$3 local port=$4 #----------------- local result= if [ -n "$command" ] then if $USBIP_EXEC $command ${bus:+--busid=$bus} ${host:+--remote=$host} ${port:+--port $port} 1> /dev/null 2> /dev/null then einfo "Executed command '$command'${bus:+ with bus '$bus'}${host:+ on host '$host'}${port:+ on port '$port'}, successfully." else ewarn "Executing command '$command'${bus:+ with bus '$bus'}${host:+ on host '$host'}${port:+ on port '$port'} failed." result=failed fi fi [ -z "$result" ] } ValidateCommand () { local command=$1 local bus_or_device=$2 local host=$3 #----------------- local result= local bus= if [ -z "$host" -o -n "$(echo $host | grep '^[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$')" ] then if [ -n "$(echo $bus_or_device | grep '^[[:xdigit:]]\{4\}:[[:xdigit:]]\{4\}$')" ] then bus="$(GetBus $bus_or_device $host)" if [ -z "$bus" ] then ewarn "Device '$bus_or_device' not available${host:+ on host '$host'}." result=failed fi else if [ -n "$(echo $bus_or_device | grep '^[0-9][0-9]*-[0-9][0-9]*$')" ] then bus=$bus_or_device else ewarn "Unrecognized bus or device '$bus_or_device'." result=failed fi fi if [ -n "$bus" ] then case "$command" in "bind"|"unbind") ExecuteUsbip $command $bus || result=failed;; "attach") if [ -n "$host" ] then ExecuteUsbip $command $bus $host || result=failed else ewarn "Host statement is missing in command '$command'." result=failed fi ;; *) ewarn "Unhandled command '$command'."; result=failed;; esac fi else ewarn "Illegal host ip address '$host'." result=failed fi [ -z "$result" ] } ProcessList () { local command=$1 shift local list=$* #----------------- local result= local no_host= case "$command" in "bind"|"unbind") no_host=yes;; *) no_host=;; esac local host= local item= ( for item in $list do if [ -n "$host" -o -n "$no_host" ] then ValidateCommand $command $item $host || result=failed host= else host=$item fi done [ -z "$result" ] ) } DetachAll () { # FIXME: At this stage, there is no way to get the vhci_hcd port id of any attached device for port in $(seq 0 15) do $USBIP_EXEC detach --port $port 2> /dev/null done [ 1 -eq 1 ] } UnbindAll () { local result= ProcessList unbind "$($USBIP_EXEC list --parsable --local | sed -n 's|^busid=\([0-9][0-9]*-[0-9][0-9]*\)#.*=usbip-host#$|\1|p' | tr '\n' ' ')" } start_daemon() { ebegin "Starting usbip daemon" if LoadKernelModule usbip-host then start-stop-daemon --start --exec $USBIP_EXEC_DAEMON -- -D fi eend $? } start() { ebegin "Starting usbip" if LoadKernelModule usbip-core then if LoadKernelModule vhci-hcd then eend 0 if yesno "${USBIP_START_DAEMON:-no}" then start_daemon fi if [ -n "$USBIP_AUTO_BIND" ] then ebegin "Auto-binding local busses" ProcessList bind $USBIP_AUTO_BIND eend $? fi if [ -n "$USBIP_AUTO_ATTACH" ] then ebegin "Auto-attaching remote busses" ProcessList attach $USBIP_AUTO_ATTACH eend $? fi else eend 1 fi else eend 1 fi } stop_daemon() { ebegin "Stopping usbip daemon" start-stop-daemon --stop --exec $USBIP_EXEC_DAEMON eend $? } stop() { ebegin "Detaching remote busses" DetachAll eend $? ebegin "Un-binding local busses" UnbindAll eend $? if [ -n "$(pidof $(basename "$USBIP_EXEC_DAEMON"))" ] then stop_daemon fi }