Stephen Warren | 3045d7f | 2016-01-15 11:15:30 -0700 | [diff] [blame] | 1 | # Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved. |
| 2 | # |
| 3 | # SPDX-License-Identifier: GPL-2.0 |
| 4 | |
| 5 | # Test U-Boot's "ums" command. At present, this test only ensures that a UMS |
| 6 | # device can be enumerated by the host/test machine. In the future, this test |
| 7 | # should be enhanced to validate disk IO. |
| 8 | |
| 9 | import os |
| 10 | import pytest |
| 11 | import time |
| 12 | |
| 13 | ''' |
| 14 | Note: This test relies on: |
| 15 | |
| 16 | a) boardenv_* to contain configuration values to define which USB ports are |
| 17 | available for testing. Without this, this test will be automatically skipped. |
| 18 | For example: |
| 19 | |
| 20 | env__usb_dev_ports = ( |
| 21 | {'tgt_usb_ctlr': '0', 'host_ums_dev_node': '/dev/disk/by-path/pci-0000:00:14.0-usb-0:13:1.0-scsi-0:0:0:0'}, |
| 22 | ) |
| 23 | |
| 24 | env__block_devs = ( |
| 25 | {'type': 'mmc', 'id': '0'}, # eMMC; always present |
| 26 | {'type': 'mmc', 'id': '1'}, # SD card; present since I plugged one in |
| 27 | ) |
| 28 | |
| 29 | b) udev rules to set permissions on devices nodes, so that sudo is not |
| 30 | required. For example: |
| 31 | |
| 32 | ACTION=="add", SUBSYSTEM=="block", SUBSYSTEMS=="usb", KERNELS=="3-13", MODE:="666" |
| 33 | |
| 34 | (You may wish to change the group ID instead of setting the permissions wide |
| 35 | open. All that matters is that the user ID running the test can access the |
| 36 | device.) |
| 37 | ''' |
| 38 | |
| 39 | def open_ums_device(host_ums_dev_node): |
| 40 | '''Attempt to open a device node, returning either the opened file handle, |
| 41 | or None on any error.''' |
| 42 | |
| 43 | try: |
| 44 | return open(host_ums_dev_node, 'rb') |
| 45 | except: |
| 46 | return None |
| 47 | |
| 48 | def wait_for_ums_device(host_ums_dev_node): |
| 49 | '''Continually attempt to open the device node exported by the "ums" |
| 50 | command, and either return the opened file handle, or raise an exception |
| 51 | after a timeout.''' |
| 52 | |
| 53 | for i in xrange(100): |
| 54 | fh = open_ums_device(host_ums_dev_node) |
| 55 | if fh: |
| 56 | return fh |
| 57 | time.sleep(0.1) |
| 58 | raise Exception('UMS device did not appear') |
| 59 | |
| 60 | def wait_for_ums_device_gone(host_ums_dev_node): |
| 61 | '''Continually attempt to open the device node exported by the "ums" |
| 62 | command, and either return once the device has disappeared, or raise an |
| 63 | exception if it does not before a timeout occurs.''' |
| 64 | |
| 65 | for i in xrange(100): |
| 66 | fh = open_ums_device(host_ums_dev_node) |
| 67 | if not fh: |
| 68 | return |
| 69 | fh.close() |
| 70 | time.sleep(0.1) |
| 71 | raise Exception('UMS device did not disappear') |
| 72 | |
| 73 | @pytest.mark.buildconfigspec('cmd_usb_mass_storage') |
| 74 | def test_ums(u_boot_console, env__usb_dev_port, env__block_devs): |
| 75 | '''Test the "ums" command; the host system must be able to enumerate a UMS |
| 76 | device when "ums" is running, and this device must disappear when "ums" is |
| 77 | aborted.''' |
| 78 | |
| 79 | tgt_usb_ctlr = env__usb_dev_port['tgt_usb_ctlr'] |
| 80 | host_ums_dev_node = env__usb_dev_port['host_ums_dev_node'] |
| 81 | |
| 82 | # We're interested in testing USB device mode on each port, not the cross- |
| 83 | # product of that with each device. So, just pick the first entry in the |
| 84 | # device list here. We'll test each block device somewhere else. |
| 85 | tgt_dev_type = env__block_devs[0]['type'] |
| 86 | tgt_dev_id = env__block_devs[0]['id'] |
| 87 | |
| 88 | cmd = 'ums %s %s %s' % (tgt_usb_ctlr, tgt_dev_type, tgt_dev_id) |
| 89 | u_boot_console.run_command('ums 0 mmc 0', wait_for_prompt=False) |
| 90 | fh = wait_for_ums_device(host_ums_dev_node) |
| 91 | fh.read(4096) |
| 92 | fh.close() |
| 93 | u_boot_console.ctrlc() |
| 94 | wait_for_ums_device_gone(host_ums_dev_node) |