0001
0002
0003
0004
0005
0006
0007
0008
0009 BASE=${0%/*}
0010 DEBUGFS=
0011 GPIO_DEBUGFS=
0012 dev_type="cdev"
0013 module="gpio-mockup"
0014 verbose=
0015 full_test=
0016 random=
0017 uapi_opt=
0018 active_opt=
0019 bias_opt=
0020 line_set_pid=
0021
0022
0023 ksft_fail=1
0024 ksft_skip=4
0025
0026 usage()
0027 {
0028 echo "Usage:"
0029 echo "$0 [-frv] [-t type]"
0030 echo "-f: full test (minimal set run by default)"
0031 echo "-r: test random lines as well as fence posts"
0032 echo "-t: interface type:"
0033 echo " cdev (character device ABI) - default"
0034 echo " cdev_v1 (deprecated character device ABI)"
0035 echo " sysfs (deprecated SYSFS ABI)"
0036 echo "-v: verbose progress reporting"
0037 exit $ksft_fail
0038 }
0039
0040 skip()
0041 {
0042 echo "$*" >&2
0043 echo "GPIO $module test SKIP"
0044 exit $ksft_skip
0045 }
0046
0047 prerequisite()
0048 {
0049 [ $(id -u) -eq 0 ] || skip "must be run as root"
0050
0051 DEBUGFS=$(grep -w debugfs /proc/mounts | cut -f2 -d' ')
0052 [ -d "$DEBUGFS" ] || skip "debugfs is not mounted"
0053
0054 GPIO_DEBUGFS=$DEBUGFS/$module
0055 }
0056
0057 remove_module()
0058 {
0059 modprobe -r -q $module
0060 }
0061
0062 cleanup()
0063 {
0064 set +e
0065 release_line
0066 remove_module
0067 jobs -p | xargs -r kill > /dev/null 2>&1
0068 }
0069
0070 fail()
0071 {
0072 echo "test failed: $*" >&2
0073 echo "GPIO $module test FAIL"
0074 exit $ksft_fail
0075 }
0076
0077 try_insert_module()
0078 {
0079 modprobe -q $module "$1" || fail "insert $module failed with error $?"
0080 }
0081
0082 log()
0083 {
0084 [ -z "$verbose" ] || echo "$*"
0085 }
0086
0087
0088
0089
0090
0091
0092
0093
0094 release_line()
0095 {
0096 [ "$line_set_pid" ] && kill $line_set_pid && wait $line_set_pid || true
0097 line_set_pid=
0098 }
0099
0100
0101 get_line()
0102 {
0103 release_line
0104
0105 local cdev_opts=${uapi_opt}${active_opt}
0106 $BASE/gpio-mockup-cdev $cdev_opts /dev/$chip $offset
0107 echo $?
0108 }
0109
0110
0111
0112
0113
0114
0115 set_line()
0116 {
0117 local val=
0118
0119 release_line
0120
0121
0122 for option in $*; do
0123 case $option in
0124 active-low)
0125 active_opt="-l "
0126 ;;
0127 active-high)
0128 active_opt=
0129 ;;
0130 bias-none)
0131 bias_opt=
0132 ;;
0133 pull-down)
0134 bias_opt="-bpull-down "
0135 ;;
0136 pull-up)
0137 bias_opt="-bpull-up "
0138 ;;
0139 0)
0140 val=0
0141 ;;
0142 1)
0143 val=1
0144 ;;
0145 esac
0146 done
0147
0148 local cdev_opts=${uapi_opt}${active_opt}
0149 if [ "$val" ]; then
0150 $BASE/gpio-mockup-cdev $cdev_opts -s$val /dev/$chip $offset &
0151
0152 line_set_pid=$!
0153
0154
0155 sleep 0.01
0156 elif [ "$bias_opt" ]; then
0157 cdev_opts=${cdev_opts}${bias_opt}
0158 $BASE/gpio-mockup-cdev $cdev_opts /dev/$chip $offset || true
0159 fi
0160 }
0161
0162 assert_line()
0163 {
0164 local val
0165
0166 val=$(get_line)
0167 [ "$val" = "$1" ] || fail "line value is ${val:-empty} when $1 was expected"
0168 }
0169
0170
0171 assert_mock()
0172 {
0173 local backoff_wait=10
0174 local retry=0
0175 local val
0176
0177 while true; do
0178 val=$(< $mock_line)
0179 [ "$val" = "$1" ] && break
0180 retry=$((retry + 1))
0181 [ $retry -lt 5 ] || fail "mockup $mock_line value ${val:-empty} when $1 expected"
0182 sleep $(printf "%0.2f" $((backoff_wait))e-3)
0183 backoff_wait=$((backoff_wait * 2))
0184 done
0185 }
0186
0187 set_mock()
0188 {
0189 echo "$1" > $mock_line
0190
0191 assert_mock "$1"
0192 }
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202 test_line()
0203 {
0204 chip=$1
0205 offset=$2
0206 log "test_line $chip $offset"
0207 mock_line=$GPIO_DEBUGFS/$chip/$offset
0208 [ -e "$mock_line" ] || fail "missing line $chip:$offset"
0209
0210
0211 set_mock 1
0212 set_line input active-high
0213 assert_line 1
0214 set_mock 0
0215 assert_line 0
0216 set_mock 1
0217 assert_line 1
0218
0219 if [ "$full_test" ]; then
0220 if [ "$dev_type" != "sysfs" ]; then
0221
0222 set_mock 0
0223 set_line input pull-up
0224 assert_line 1
0225 set_mock 0
0226 assert_line 0
0227
0228 set_mock 1
0229 set_line input pull-down
0230 assert_line 0
0231 set_mock 1
0232 assert_line 1
0233
0234 set_line bias-none
0235 fi
0236
0237
0238 set_mock 0
0239 set_line active-low
0240 assert_line 1
0241 set_mock 1
0242 assert_line 0
0243 set_mock 0
0244 assert_line 1
0245
0246
0247 set_mock 1
0248 set_line active-high 0
0249 assert_mock 0
0250 set_line 1
0251 assert_mock 1
0252 set_line 0
0253 assert_mock 0
0254 fi
0255
0256
0257 set_mock 0
0258 set_line active-low 0
0259 assert_mock 1
0260 set_line 1
0261 assert_mock 0
0262 set_line 0
0263 assert_mock 1
0264
0265 release_line
0266 }
0267
0268 test_no_line()
0269 {
0270 log test_no_line "$*"
0271 [ ! -e "$GPIO_DEBUGFS/$1/$2" ] || fail "unexpected line $1:$2"
0272 }
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286 insmod_test()
0287 {
0288 local ranges=
0289 local gc=
0290 local width=
0291
0292 [ "${1:-}" ] || fail "missing ranges"
0293 ranges=$1 ; shift
0294 try_insert_module "gpio_mockup_ranges=$ranges"
0295 log "GPIO $module test with ranges: <$ranges>:"
0296
0297 gpiochip=$(find "$DEBUGFS/$module/" -name gpiochip* -type d | sort)
0298 for chip in $gpiochip; do
0299 gc=${chip
0300 [ "${1:-}" ] || fail "unexpected chip - $gc"
0301 width=$1 ; shift
0302 test_line $gc 0
0303 if [ "$random" -a $width -gt 2 ]; then
0304 test_line $gc $((RANDOM % ($width - 2) + 1))
0305 fi
0306 test_line $gc $(($width - 1))
0307 test_no_line $gc $width
0308 done
0309 [ "${1:-}" ] && fail "missing expected chip of width $1"
0310 remove_module || fail "failed to remove module with error $?"
0311 }
0312
0313 while getopts ":frvt:" opt; do
0314 case $opt in
0315 f)
0316 full_test=true
0317 ;;
0318 r)
0319 random=true
0320 ;;
0321 t)
0322 dev_type=$OPTARG
0323 ;;
0324 v)
0325 verbose=true
0326 ;;
0327 *)
0328 usage
0329 ;;
0330 esac
0331 done
0332 shift $((OPTIND - 1))
0333
0334 [ "${1:-}" ] && fail "unknown argument '$1'"
0335
0336 prerequisite
0337
0338 trap 'exit $ksft_fail' SIGTERM SIGINT
0339 trap cleanup EXIT
0340
0341 case "$dev_type" in
0342 sysfs)
0343 source $BASE/gpio-mockup-sysfs.sh
0344 echo "WARNING: gpio sysfs ABI is deprecated."
0345 ;;
0346 cdev_v1)
0347 echo "WARNING: gpio cdev ABI v1 is deprecated."
0348 uapi_opt="-u1 "
0349 ;;
0350 cdev)
0351 ;;
0352 *)
0353 fail "unknown interface type: $dev_type"
0354 ;;
0355 esac
0356
0357 remove_module || fail "can't remove existing $module module"
0358
0359
0360 [ "$full_test" -a -e "/dev/gpiochip0" ] && skip "full tests conflict with gpiochip0"
0361
0362 echo "1. Module load tests"
0363 echo "1.1. dynamic allocation of gpio"
0364 insmod_test "-1,32" 32
0365 insmod_test "-1,23,-1,32" 23 32
0366 insmod_test "-1,23,-1,26,-1,32" 23 26 32
0367 if [ "$full_test" ]; then
0368 echo "1.2. manual allocation of gpio"
0369 insmod_test "0,32" 32
0370 insmod_test "0,32,32,60" 32 28
0371 insmod_test "0,32,40,64,64,96" 32 24 32
0372 echo "1.3. dynamic and manual allocation of gpio"
0373 insmod_test "-1,32,32,62" 32 30
0374 insmod_test "-1,22,-1,23,0,24,32,64" 22 23 24 32
0375 insmod_test "-1,32,32,60,-1,29" 32 28 29
0376 insmod_test "-1,32,40,64,-1,5" 32 24 5
0377 insmod_test "0,32,32,44,-1,22,-1,31" 32 12 22 31
0378 fi
0379 echo "2. Module load error tests"
0380 echo "2.1 gpio overflow"
0381
0382 insmod_test "-1,1024"
0383 if [ "$full_test" ]; then
0384 echo "2.2 no lines defined"
0385 insmod_test "0,0"
0386 echo "2.3 ignore range overlap"
0387 insmod_test "0,32,0,1" 32
0388 insmod_test "0,32,1,5" 32
0389 insmod_test "0,32,30,35" 32
0390 insmod_test "0,32,31,32" 32
0391 insmod_test "10,32,30,35" 22
0392 insmod_test "10,32,9,14" 22
0393 insmod_test "0,32,20,21,40,56" 32 16
0394 insmod_test "0,32,32,64,32,40" 32 32
0395 insmod_test "0,32,32,64,36,37" 32 32
0396 insmod_test "0,32,35,64,34,36" 32 29
0397 insmod_test "0,30,35,64,35,45" 30 29
0398 insmod_test "0,32,40,56,30,33" 32 16
0399 insmod_test "0,32,40,56,30,41" 32 16
0400 insmod_test "0,32,40,56,39,45" 32 16
0401 fi
0402
0403 echo "GPIO $module test PASS"