aboutsummaryrefslogtreecommitdiffstats
path: root/testing/usbip-utils/usbip.initd
blob: 58e2358c31c4f98e3f6ea6b4e4f40ab2e533f5ec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
#!/sbin/runscript

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=$(/sbin/modprobe -l $module)
    if [ -n "$filename" ]
    then
      if ! /sbin/modprobe $filename
      then
        eerror "Cannot load kernel module '$filename'."
        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
}