Repostiory containing DAPLink source code with Reset Pin workaround for HANI_IOT board.
Upstream: https://github.com/ARMmbed/DAPLink
test/usb_test.py@0:01f31e923fe2, 2020-04-07 (annotated)
- Committer:
- Pawel Zarembski
- Date:
- Tue Apr 07 12:55:42 2020 +0200
- Revision:
- 0:01f31e923fe2
hani: DAPLink with reset workaround
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Pawel Zarembski |
0:01f31e923fe2 | 1 | # |
Pawel Zarembski |
0:01f31e923fe2 | 2 | # DAPLink Interface Firmware |
Pawel Zarembski |
0:01f31e923fe2 | 3 | # Copyright (c) 2016-2016, ARM Limited, All Rights Reserved |
Pawel Zarembski |
0:01f31e923fe2 | 4 | # SPDX-License-Identifier: Apache-2.0 |
Pawel Zarembski |
0:01f31e923fe2 | 5 | # |
Pawel Zarembski |
0:01f31e923fe2 | 6 | # Licensed under the Apache License, Version 2.0 (the "License"); you may |
Pawel Zarembski |
0:01f31e923fe2 | 7 | # not use this file except in compliance with the License. |
Pawel Zarembski |
0:01f31e923fe2 | 8 | # You may obtain a copy of the License at |
Pawel Zarembski |
0:01f31e923fe2 | 9 | # |
Pawel Zarembski |
0:01f31e923fe2 | 10 | # http://www.apache.org/licenses/LICENSE-2.0 |
Pawel Zarembski |
0:01f31e923fe2 | 11 | # |
Pawel Zarembski |
0:01f31e923fe2 | 12 | # Unless required by applicable law or agreed to in writing, software |
Pawel Zarembski |
0:01f31e923fe2 | 13 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
Pawel Zarembski |
0:01f31e923fe2 | 14 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
Pawel Zarembski |
0:01f31e923fe2 | 15 | # See the License for the specific language governing permissions and |
Pawel Zarembski |
0:01f31e923fe2 | 16 | # limitations under the License. |
Pawel Zarembski |
0:01f31e923fe2 | 17 | # |
Pawel Zarembski |
0:01f31e923fe2 | 18 | """ Module for low level and targeted USB tests""" |
Pawel Zarembski |
0:01f31e923fe2 | 19 | |
Pawel Zarembski |
0:01f31e923fe2 | 20 | from __future__ import print_function |
Pawel Zarembski |
0:01f31e923fe2 | 21 | |
Pawel Zarembski |
0:01f31e923fe2 | 22 | import os |
Pawel Zarembski |
0:01f31e923fe2 | 23 | import usb.core |
Pawel Zarembski |
0:01f31e923fe2 | 24 | import functools |
Pawel Zarembski |
0:01f31e923fe2 | 25 | import threading |
Pawel Zarembski |
0:01f31e923fe2 | 26 | import time |
Pawel Zarembski |
0:01f31e923fe2 | 27 | from usb_cdc import USBCdc |
Pawel Zarembski |
0:01f31e923fe2 | 28 | from usb_hid import USBHid |
Pawel Zarembski |
0:01f31e923fe2 | 29 | from usb_msd import USBMsd, Fat |
Pawel Zarembski |
0:01f31e923fe2 | 30 | |
Pawel Zarembski |
0:01f31e923fe2 | 31 | DISMOUNT_TIME_S = 10.00 |
Pawel Zarembski |
0:01f31e923fe2 | 32 | |
Pawel Zarembski |
0:01f31e923fe2 | 33 | |
Pawel Zarembski |
0:01f31e923fe2 | 34 | def test_usb(workspace, parent_test, force=False): |
Pawel Zarembski |
0:01f31e923fe2 | 35 | """Run raw USB tests |
Pawel Zarembski |
0:01f31e923fe2 | 36 | |
Pawel Zarembski |
0:01f31e923fe2 | 37 | Requirements: |
Pawel Zarembski |
0:01f31e923fe2 | 38 | -daplink-validation must be loaded for the target. |
Pawel Zarembski |
0:01f31e923fe2 | 39 | """ |
Pawel Zarembski |
0:01f31e923fe2 | 40 | |
Pawel Zarembski |
0:01f31e923fe2 | 41 | # Only test on supported platforms |
Pawel Zarembski |
0:01f31e923fe2 | 42 | if not _platform_supports_usb_test() and not force: |
Pawel Zarembski |
0:01f31e923fe2 | 43 | parent_test.info("Skipping USB test on this platform") |
Pawel Zarembski |
0:01f31e923fe2 | 44 | return |
Pawel Zarembski |
0:01f31e923fe2 | 45 | test_info = parent_test.create_subtest("USB test") |
Pawel Zarembski |
0:01f31e923fe2 | 46 | |
Pawel Zarembski |
0:01f31e923fe2 | 47 | # Find the device under test |
Pawel Zarembski |
0:01f31e923fe2 | 48 | serial_number = workspace.board.get_unique_id() |
Pawel Zarembski |
0:01f31e923fe2 | 49 | dev = _daplink_from_serial_number(serial_number) |
Pawel Zarembski |
0:01f31e923fe2 | 50 | if dev is None: |
Pawel Zarembski |
0:01f31e923fe2 | 51 | test_info.failure("Could not find board with serial number %s" % |
Pawel Zarembski |
0:01f31e923fe2 | 52 | serial_number) |
Pawel Zarembski |
0:01f31e923fe2 | 53 | return |
Pawel Zarembski |
0:01f31e923fe2 | 54 | |
Pawel Zarembski |
0:01f31e923fe2 | 55 | # Create wrappers for and acquire exclusive access to interfaces |
Pawel Zarembski |
0:01f31e923fe2 | 56 | cdc = USBCdc(dev) |
Pawel Zarembski |
0:01f31e923fe2 | 57 | hid = USBHid(dev) |
Pawel Zarembski |
0:01f31e923fe2 | 58 | msd = USBMsd(dev) |
Pawel Zarembski |
0:01f31e923fe2 | 59 | cdc.lock() |
Pawel Zarembski |
0:01f31e923fe2 | 60 | hid.lock() |
Pawel Zarembski |
0:01f31e923fe2 | 61 | msd.lock() |
Pawel Zarembski |
0:01f31e923fe2 | 62 | |
Pawel Zarembski |
0:01f31e923fe2 | 63 | try: |
Pawel Zarembski |
0:01f31e923fe2 | 64 | |
Pawel Zarembski |
0:01f31e923fe2 | 65 | for usb_test_on in (False, True): |
Pawel Zarembski |
0:01f31e923fe2 | 66 | |
Pawel Zarembski |
0:01f31e923fe2 | 67 | _set_usb_test_mode(hid, usb_test_on) |
Pawel Zarembski |
0:01f31e923fe2 | 68 | |
Pawel Zarembski |
0:01f31e923fe2 | 69 | test_cdc(test_info, cdc) |
Pawel Zarembski |
0:01f31e923fe2 | 70 | |
Pawel Zarembski |
0:01f31e923fe2 | 71 | test_hid(test_info, hid) |
Pawel Zarembski |
0:01f31e923fe2 | 72 | |
Pawel Zarembski |
0:01f31e923fe2 | 73 | test_msd(test_info, msd) |
Pawel Zarembski |
0:01f31e923fe2 | 74 | |
Pawel Zarembski |
0:01f31e923fe2 | 75 | test_msd_stall(test_info, msd) |
Pawel Zarembski |
0:01f31e923fe2 | 76 | |
Pawel Zarembski |
0:01f31e923fe2 | 77 | test_control(test_info, dev, cdc, hid, msd) |
Pawel Zarembski |
0:01f31e923fe2 | 78 | |
Pawel Zarembski |
0:01f31e923fe2 | 79 | test_all(test_info, cdc, hid, msd) |
Pawel Zarembski |
0:01f31e923fe2 | 80 | |
Pawel Zarembski |
0:01f31e923fe2 | 81 | # TODO - future enhancements |
Pawel Zarembski |
0:01f31e923fe2 | 82 | # MSD remount + hid |
Pawel Zarembski |
0:01f31e923fe2 | 83 | # STALL IN and STALL OUT |
Pawel Zarembski |
0:01f31e923fe2 | 84 | |
Pawel Zarembski |
0:01f31e923fe2 | 85 | finally: |
Pawel Zarembski |
0:01f31e923fe2 | 86 | try: |
Pawel Zarembski |
0:01f31e923fe2 | 87 | _set_usb_test_mode(hid, False) |
Pawel Zarembski |
0:01f31e923fe2 | 88 | except usb.core.USBError: |
Pawel Zarembski |
0:01f31e923fe2 | 89 | pass |
Pawel Zarembski |
0:01f31e923fe2 | 90 | cdc.unlock() |
Pawel Zarembski |
0:01f31e923fe2 | 91 | hid.unlock() |
Pawel Zarembski |
0:01f31e923fe2 | 92 | msd.unlock() |
Pawel Zarembski |
0:01f31e923fe2 | 93 | |
Pawel Zarembski |
0:01f31e923fe2 | 94 | |
Pawel Zarembski |
0:01f31e923fe2 | 95 | def main(): |
Pawel Zarembski |
0:01f31e923fe2 | 96 | """Run the usb test as a stand alone program""" |
Pawel Zarembski |
0:01f31e923fe2 | 97 | |
Pawel Zarembski |
0:01f31e923fe2 | 98 | import test_info |
Pawel Zarembski |
0:01f31e923fe2 | 99 | import mock |
Pawel Zarembski |
0:01f31e923fe2 | 100 | |
Pawel Zarembski |
0:01f31e923fe2 | 101 | def get_unique_id(unique_id): |
Pawel Zarembski |
0:01f31e923fe2 | 102 | """Mock function to return a unique id""" |
Pawel Zarembski |
0:01f31e923fe2 | 103 | return unique_id |
Pawel Zarembski |
0:01f31e923fe2 | 104 | |
Pawel Zarembski |
0:01f31e923fe2 | 105 | dev_list = usb.core.find(find_all=True, custom_match=_daplink_match) |
Pawel Zarembski |
0:01f31e923fe2 | 106 | for dev in dev_list: |
Pawel Zarembski |
0:01f31e923fe2 | 107 | board_id = dev.serial_number |
Pawel Zarembski |
0:01f31e923fe2 | 108 | print("Testing board %s" % board_id) |
Pawel Zarembski |
0:01f31e923fe2 | 109 | print("----------------") |
Pawel Zarembski |
0:01f31e923fe2 | 110 | mock_ws = mock.Mock() |
Pawel Zarembski |
0:01f31e923fe2 | 111 | mock_ws.board = mock.Mock() |
Pawel Zarembski |
0:01f31e923fe2 | 112 | mock_ws.board.unique_id = dev.serial_number |
Pawel Zarembski |
0:01f31e923fe2 | 113 | mock_ws.board.get_unique_id = functools.partial(get_unique_id, |
Pawel Zarembski |
0:01f31e923fe2 | 114 | board_id) |
Pawel Zarembski |
0:01f31e923fe2 | 115 | test_usb(mock_ws, test_info.TestInfoStub(), True) |
Pawel Zarembski |
0:01f31e923fe2 | 116 | |
Pawel Zarembski |
0:01f31e923fe2 | 117 | |
Pawel Zarembski |
0:01f31e923fe2 | 118 | def test_cdc(test_info, cdc): |
Pawel Zarembski |
0:01f31e923fe2 | 119 | """Smoke test of the CDC endpoint""" |
Pawel Zarembski |
0:01f31e923fe2 | 120 | cdc.set_line_coding(115200) |
Pawel Zarembski |
0:01f31e923fe2 | 121 | baud, fmt, parity, databits = cdc.get_line_coding() |
Pawel Zarembski |
0:01f31e923fe2 | 122 | test_info.info("Baud %i, fmt %i, parity %i, databits %i" % |
Pawel Zarembski |
0:01f31e923fe2 | 123 | (baud, fmt, parity, databits)) |
Pawel Zarembski |
0:01f31e923fe2 | 124 | cdc.send_break(cdc.SEND_BREAK_ON) |
Pawel Zarembski |
0:01f31e923fe2 | 125 | cdc.send_break(cdc.SEND_BREAK_OFF) |
Pawel Zarembski |
0:01f31e923fe2 | 126 | data = cdc.read(1024) |
Pawel Zarembski |
0:01f31e923fe2 | 127 | test_info.info("Serial port data: %s" % bytearray(data)) |
Pawel Zarembski |
0:01f31e923fe2 | 128 | cdc.write("Hello world") |
Pawel Zarembski |
0:01f31e923fe2 | 129 | data = cdc.read(1024) |
Pawel Zarembski |
0:01f31e923fe2 | 130 | test_info.info("Serial port data2: %s" % bytearray(data)) |
Pawel Zarembski |
0:01f31e923fe2 | 131 | |
Pawel Zarembski |
0:01f31e923fe2 | 132 | |
Pawel Zarembski |
0:01f31e923fe2 | 133 | def test_hid(test_info, hid): |
Pawel Zarembski |
0:01f31e923fe2 | 134 | """Smoke test of the HID endpoint""" |
Pawel Zarembski |
0:01f31e923fe2 | 135 | hid.set_idle() |
Pawel Zarembski |
0:01f31e923fe2 | 136 | report = hid.get_descriptor(hid.DESC_TYPE_REPORT, 0) |
Pawel Zarembski |
0:01f31e923fe2 | 137 | test_info.info("Report descriptor: %s" % report) |
Pawel Zarembski |
0:01f31e923fe2 | 138 | # Send CMSIS-DAP vendor command to get the serial number |
Pawel Zarembski |
0:01f31e923fe2 | 139 | data = bytearray(64) |
Pawel Zarembski |
0:01f31e923fe2 | 140 | data[0] = 0x80 |
Pawel Zarembski |
0:01f31e923fe2 | 141 | hid.set_report(data) |
Pawel Zarembski |
0:01f31e923fe2 | 142 | resp = hid.get_report(64) |
Pawel Zarembski |
0:01f31e923fe2 | 143 | length = resp[1] |
Pawel Zarembski |
0:01f31e923fe2 | 144 | test_info.info("CMSIS-DAP response: %s" % |
Pawel Zarembski |
0:01f31e923fe2 | 145 | bytearray(resp[1:1 + length]).decode("utf-8")) |
Pawel Zarembski |
0:01f31e923fe2 | 146 | |
Pawel Zarembski |
0:01f31e923fe2 | 147 | |
Pawel Zarembski |
0:01f31e923fe2 | 148 | def test_msd(test_info, msd): |
Pawel Zarembski |
0:01f31e923fe2 | 149 | """MSD endpoint tests""" |
Pawel Zarembski |
0:01f31e923fe2 | 150 | |
Pawel Zarembski |
0:01f31e923fe2 | 151 | # Simple read |
Pawel Zarembski |
0:01f31e923fe2 | 152 | mbr = msd.scsi_read10(0, 1) |
Pawel Zarembski |
0:01f31e923fe2 | 153 | test_info.info("MBR[0:16]: %s" % mbr[0:16]) |
Pawel Zarembski |
0:01f31e923fe2 | 154 | |
Pawel Zarembski |
0:01f31e923fe2 | 155 | # Test FAT filesystem |
Pawel Zarembski |
0:01f31e923fe2 | 156 | fat = Fat(msd) |
Pawel Zarembski |
0:01f31e923fe2 | 157 | print(fat.mbr) |
Pawel Zarembski |
0:01f31e923fe2 | 158 | |
Pawel Zarembski |
0:01f31e923fe2 | 159 | # Grab entries in the root directory |
Pawel Zarembski |
0:01f31e923fe2 | 160 | root_dir = fat.root_dir |
Pawel Zarembski |
0:01f31e923fe2 | 161 | for entry in root_dir: |
Pawel Zarembski |
0:01f31e923fe2 | 162 | if entry["DIR_Name"][0] != "\0": |
Pawel Zarembski |
0:01f31e923fe2 | 163 | print(entry) |
Pawel Zarembski |
0:01f31e923fe2 | 164 | |
Pawel Zarembski |
0:01f31e923fe2 | 165 | # Trigger a remount |
Pawel Zarembski |
0:01f31e923fe2 | 166 | dir_idx = root_dir.find_free_entry_index() |
Pawel Zarembski |
0:01f31e923fe2 | 167 | root_dir[dir_idx]["DIR_Name"] = "REFRESH ACT" |
Pawel Zarembski |
0:01f31e923fe2 | 168 | root_dir_data = root_dir.pack() |
Pawel Zarembski |
0:01f31e923fe2 | 169 | msd.scsi_write10(root_dir.sector, root_dir_data) |
Pawel Zarembski |
0:01f31e923fe2 | 170 | |
Pawel Zarembski |
0:01f31e923fe2 | 171 | test_info.info("Added file to root directory") |
Pawel Zarembski |
0:01f31e923fe2 | 172 | start = time.time() |
Pawel Zarembski |
0:01f31e923fe2 | 173 | while time.time() - start < DISMOUNT_TIME_S: |
Pawel Zarembski |
0:01f31e923fe2 | 174 | try: |
Pawel Zarembski |
0:01f31e923fe2 | 175 | msd.scsi_read10(0, 1) |
Pawel Zarembski |
0:01f31e923fe2 | 176 | except msd.SCSIError: |
Pawel Zarembski |
0:01f31e923fe2 | 177 | test_info.info("Dismount detected") |
Pawel Zarembski |
0:01f31e923fe2 | 178 | break |
Pawel Zarembski |
0:01f31e923fe2 | 179 | else: |
Pawel Zarembski |
0:01f31e923fe2 | 180 | test_info.failure("Device failed to dismount") |
Pawel Zarembski |
0:01f31e923fe2 | 181 | |
Pawel Zarembski |
0:01f31e923fe2 | 182 | start = time.time() |
Pawel Zarembski |
0:01f31e923fe2 | 183 | while time.time() - start < DISMOUNT_TIME_S: |
Pawel Zarembski |
0:01f31e923fe2 | 184 | try: |
Pawel Zarembski |
0:01f31e923fe2 | 185 | msd.scsi_read10(0, 1) |
Pawel Zarembski |
0:01f31e923fe2 | 186 | test_info.info("Mount detected") |
Pawel Zarembski |
0:01f31e923fe2 | 187 | break |
Pawel Zarembski |
0:01f31e923fe2 | 188 | except msd.SCSIError: |
Pawel Zarembski |
0:01f31e923fe2 | 189 | pass |
Pawel Zarembski |
0:01f31e923fe2 | 190 | else: |
Pawel Zarembski |
0:01f31e923fe2 | 191 | test_info.failure("Device failed to mount") |
Pawel Zarembski |
0:01f31e923fe2 | 192 | |
Pawel Zarembski |
0:01f31e923fe2 | 193 | |
Pawel Zarembski |
0:01f31e923fe2 | 194 | def test_msd_stall(test_info, msd): |
Pawel Zarembski |
0:01f31e923fe2 | 195 | """Test stalls coming at various times in the middle of MSD xfers""" |
Pawel Zarembski |
0:01f31e923fe2 | 196 | fat = Fat(msd) |
Pawel Zarembski |
0:01f31e923fe2 | 197 | root_dir = fat.root_dir |
Pawel Zarembski |
0:01f31e923fe2 | 198 | dir_idx = root_dir.find_free_entry_index() |
Pawel Zarembski |
0:01f31e923fe2 | 199 | root_dir[dir_idx]["DIR_Name"] = "REFRESH ACT" |
Pawel Zarembski |
0:01f31e923fe2 | 200 | root_dir_data = root_dir.pack() |
Pawel Zarembski |
0:01f31e923fe2 | 201 | |
Pawel Zarembski |
0:01f31e923fe2 | 202 | # Test that a write fails if media is removed after the CBW |
Pawel Zarembski |
0:01f31e923fe2 | 203 | # stage but before the CSW stage |
Pawel Zarembski |
0:01f31e923fe2 | 204 | msd.scsi_write10(root_dir.sector, root_dir_data) |
Pawel Zarembski |
0:01f31e923fe2 | 205 | msd.delay_cbw_to_data = 1.0 |
Pawel Zarembski |
0:01f31e923fe2 | 206 | retval = msd.CSW_STATUS_PASSED |
Pawel Zarembski |
0:01f31e923fe2 | 207 | try: |
Pawel Zarembski |
0:01f31e923fe2 | 208 | msd.scsi_write10(0, bytearray(512)) |
Pawel Zarembski |
0:01f31e923fe2 | 209 | test_info.failure("Device failed to stall data stage") |
Pawel Zarembski |
0:01f31e923fe2 | 210 | except msd.SCSIError as error: |
Pawel Zarembski |
0:01f31e923fe2 | 211 | retval = error.value |
Pawel Zarembski |
0:01f31e923fe2 | 212 | msd.delay_cbw_to_data = 0 |
Pawel Zarembski |
0:01f31e923fe2 | 213 | # Make sure device still works as expected |
Pawel Zarembski |
0:01f31e923fe2 | 214 | time.sleep(3) |
Pawel Zarembski |
0:01f31e923fe2 | 215 | msd.scsi_read10(0, 1) |
Pawel Zarembski |
0:01f31e923fe2 | 216 | msd.scsi_write10(0, bytearray(512)) |
Pawel Zarembski |
0:01f31e923fe2 | 217 | if retval == msd.CSW_STATUS_FAILED: |
Pawel Zarembski |
0:01f31e923fe2 | 218 | test_info.info("Test CBW,Stall,Data OUT - Pass") |
Pawel Zarembski |
0:01f31e923fe2 | 219 | else: |
Pawel Zarembski |
0:01f31e923fe2 | 220 | test_info.failure("Device returned wrong status") |
Pawel Zarembski |
0:01f31e923fe2 | 221 | |
Pawel Zarembski |
0:01f31e923fe2 | 222 | # Test that a write succeeds even if media is removed |
Pawel Zarembski |
0:01f31e923fe2 | 223 | # after the OUT stage but before the CSW stage |
Pawel Zarembski |
0:01f31e923fe2 | 224 | msd.scsi_write10(root_dir.sector, root_dir_data) |
Pawel Zarembski |
0:01f31e923fe2 | 225 | msd.delay_data_to_csw = 1.0 |
Pawel Zarembski |
0:01f31e923fe2 | 226 | msd.scsi_write10(0, bytearray(512)) |
Pawel Zarembski |
0:01f31e923fe2 | 227 | msd.delay_data_to_csw = 0 |
Pawel Zarembski |
0:01f31e923fe2 | 228 | # Make sure device still works as expected |
Pawel Zarembski |
0:01f31e923fe2 | 229 | time.sleep(3) |
Pawel Zarembski |
0:01f31e923fe2 | 230 | msd.scsi_read10(0, 1) |
Pawel Zarembski |
0:01f31e923fe2 | 231 | msd.scsi_write10(0, bytearray(512)) |
Pawel Zarembski |
0:01f31e923fe2 | 232 | test_info.info("Test DATA OUT,Stall,CSW - Pass") |
Pawel Zarembski |
0:01f31e923fe2 | 233 | |
Pawel Zarembski |
0:01f31e923fe2 | 234 | # Test that a read succeeds even if media is removed |
Pawel Zarembski |
0:01f31e923fe2 | 235 | # after the IN stage but before the CSW stage |
Pawel Zarembski |
0:01f31e923fe2 | 236 | msd.scsi_write10(root_dir.sector, root_dir_data) |
Pawel Zarembski |
0:01f31e923fe2 | 237 | msd.delay_data_to_csw = 1.0 |
Pawel Zarembski |
0:01f31e923fe2 | 238 | resp = msd.scsi_read10(0, 1) |
Pawel Zarembski |
0:01f31e923fe2 | 239 | assert len(resp) == 512 |
Pawel Zarembski |
0:01f31e923fe2 | 240 | msd.delay_data_to_csw = 0 |
Pawel Zarembski |
0:01f31e923fe2 | 241 | # Make sure device still works as expected |
Pawel Zarembski |
0:01f31e923fe2 | 242 | time.sleep(3) |
Pawel Zarembski |
0:01f31e923fe2 | 243 | msd.scsi_read10(0, 1) |
Pawel Zarembski |
0:01f31e923fe2 | 244 | msd.scsi_write10(0, bytearray(512)) |
Pawel Zarembski |
0:01f31e923fe2 | 245 | test_info.info("Test DATA IN,Stall,CSW - Pass") |
Pawel Zarembski |
0:01f31e923fe2 | 246 | |
Pawel Zarembski |
0:01f31e923fe2 | 247 | # Test that a test unit ready succeeds even if media is removed |
Pawel Zarembski |
0:01f31e923fe2 | 248 | # after the CBW stage but before the CSW stage |
Pawel Zarembski |
0:01f31e923fe2 | 249 | msd.scsi_write10(root_dir.sector, root_dir_data) |
Pawel Zarembski |
0:01f31e923fe2 | 250 | msd.delay_data_to_csw = 1.0 |
Pawel Zarembski |
0:01f31e923fe2 | 251 | resp = msd.scsi_test_unit_ready() |
Pawel Zarembski |
0:01f31e923fe2 | 252 | msd.delay_data_to_csw = 0 |
Pawel Zarembski |
0:01f31e923fe2 | 253 | # Make sure device still works as expected |
Pawel Zarembski |
0:01f31e923fe2 | 254 | time.sleep(3) |
Pawel Zarembski |
0:01f31e923fe2 | 255 | msd.scsi_read10(0, 1) |
Pawel Zarembski |
0:01f31e923fe2 | 256 | msd.scsi_write10(0, bytearray(512)) |
Pawel Zarembski |
0:01f31e923fe2 | 257 | if resp == msd.CSW_STATUS_PASSED: |
Pawel Zarembski |
0:01f31e923fe2 | 258 | test_info.info("Test CBW,Stall,CSW - Pass") |
Pawel Zarembski |
0:01f31e923fe2 | 259 | else: |
Pawel Zarembski |
0:01f31e923fe2 | 260 | test_info.failure("Test CBW,Stall,CSW - Failed") |
Pawel Zarembski |
0:01f31e923fe2 | 261 | |
Pawel Zarembski |
0:01f31e923fe2 | 262 | # Test that a test unit ready succeeds even if media is removed |
Pawel Zarembski |
0:01f31e923fe2 | 263 | # after the CBW stage but before the CSW stage |
Pawel Zarembski |
0:01f31e923fe2 | 264 | msd.scsi_write10(root_dir.sector, root_dir_data) |
Pawel Zarembski |
0:01f31e923fe2 | 265 | time.sleep(1.0) |
Pawel Zarembski |
0:01f31e923fe2 | 266 | resp = msd.scsi_test_unit_ready() |
Pawel Zarembski |
0:01f31e923fe2 | 267 | # Make sure device still works as expected |
Pawel Zarembski |
0:01f31e923fe2 | 268 | time.sleep(3) |
Pawel Zarembski |
0:01f31e923fe2 | 269 | msd.scsi_read10(0, 1) |
Pawel Zarembski |
0:01f31e923fe2 | 270 | msd.scsi_write10(0, bytearray(512)) |
Pawel Zarembski |
0:01f31e923fe2 | 271 | if resp == msd.CSW_STATUS_FAILED: |
Pawel Zarembski |
0:01f31e923fe2 | 272 | test_info.info("Test CBW,Stall,CSW - Pass") |
Pawel Zarembski |
0:01f31e923fe2 | 273 | else: |
Pawel Zarembski |
0:01f31e923fe2 | 274 | test_info.failure("Test CBW,Stall,CSW - Failed") |
Pawel Zarembski |
0:01f31e923fe2 | 275 | |
Pawel Zarembski |
0:01f31e923fe2 | 276 | |
Pawel Zarembski |
0:01f31e923fe2 | 277 | def test_control(test_info, dev, cdc, hid, msd): |
Pawel Zarembski |
0:01f31e923fe2 | 278 | """Test for the control endpoint""" |
Pawel Zarembski |
0:01f31e923fe2 | 279 | |
Pawel Zarembski |
0:01f31e923fe2 | 280 | test_info.info("testing control transfer with size a multiple of 256") |
Pawel Zarembski |
0:01f31e923fe2 | 281 | request_type = 0x80 |
Pawel Zarembski |
0:01f31e923fe2 | 282 | request = 0x06 # Get descriptor |
Pawel Zarembski |
0:01f31e923fe2 | 283 | value = 0x200 # Configuration descriptor |
Pawel Zarembski |
0:01f31e923fe2 | 284 | index = 0 # Always 0 for this request |
Pawel Zarembski |
0:01f31e923fe2 | 285 | resp = dev.ctrl_transfer(request_type, request, value, index, 256) |
Pawel Zarembski |
0:01f31e923fe2 | 286 | assert len(resp) > 0 |
Pawel Zarembski |
0:01f31e923fe2 | 287 | |
Pawel Zarembski |
0:01f31e923fe2 | 288 | test_info.info("testing control commands") |
Pawel Zarembski |
0:01f31e923fe2 | 289 | # Test various patterns of control transfers |
Pawel Zarembski |
0:01f31e923fe2 | 290 | # |
Pawel Zarembski |
0:01f31e923fe2 | 291 | # Some devices have had problems with back-to-back |
Pawel Zarembski |
0:01f31e923fe2 | 292 | # control transfers. Intentionally send these sequences |
Pawel Zarembski |
0:01f31e923fe2 | 293 | # to make sure they are properly handled. |
Pawel Zarembski |
0:01f31e923fe2 | 294 | for _ in range(100): |
Pawel Zarembski |
0:01f31e923fe2 | 295 | # Control transfer with a data in stage |
Pawel Zarembski |
0:01f31e923fe2 | 296 | cdc.get_line_coding() |
Pawel Zarembski |
0:01f31e923fe2 | 297 | for _ in range(100): |
Pawel Zarembski |
0:01f31e923fe2 | 298 | # Control transfer with a data out stage followed |
Pawel Zarembski |
0:01f31e923fe2 | 299 | # by a control transfer with a data in stage |
Pawel Zarembski |
0:01f31e923fe2 | 300 | cdc.set_line_coding(115200) |
Pawel Zarembski |
0:01f31e923fe2 | 301 | cdc.get_line_coding() |
Pawel Zarembski |
0:01f31e923fe2 | 302 | for _ in range(100): |
Pawel Zarembski |
0:01f31e923fe2 | 303 | # Control transfer with a data out stage |
Pawel Zarembski |
0:01f31e923fe2 | 304 | cdc.set_line_coding(115200) |
Pawel Zarembski |
0:01f31e923fe2 | 305 | |
Pawel Zarembski |
0:01f31e923fe2 | 306 | test_info.info("testing endpoint clearing") |
Pawel Zarembski |
0:01f31e923fe2 | 307 | |
Pawel Zarembski |
0:01f31e923fe2 | 308 | cdc.ep_data_out.clear_halt() |
Pawel Zarembski |
0:01f31e923fe2 | 309 | cdc.ep_data_out.write('') # DATA0 |
Pawel Zarembski |
0:01f31e923fe2 | 310 | cdc.ep_data_out.clear_halt() |
Pawel Zarembski |
0:01f31e923fe2 | 311 | cdc.ep_data_out.write('') # DATA0 |
Pawel Zarembski |
0:01f31e923fe2 | 312 | |
Pawel Zarembski |
0:01f31e923fe2 | 313 | cdc.ep_data_out.clear_halt() |
Pawel Zarembski |
0:01f31e923fe2 | 314 | cdc.ep_data_out.write('') # DATA 0 |
Pawel Zarembski |
0:01f31e923fe2 | 315 | cdc.ep_data_out.write('') # DATA 1 |
Pawel Zarembski |
0:01f31e923fe2 | 316 | cdc.ep_data_out.clear_halt() |
Pawel Zarembski |
0:01f31e923fe2 | 317 | cdc.ep_data_out.write('') # DATA 0 |
Pawel Zarembski |
0:01f31e923fe2 | 318 | |
Pawel Zarembski |
0:01f31e923fe2 | 319 | |
Pawel Zarembski |
0:01f31e923fe2 | 320 | def test_all(test_info, cdc, hid, msd): |
Pawel Zarembski |
0:01f31e923fe2 | 321 | """Test all endpoints in parallel""" |
Pawel Zarembski |
0:01f31e923fe2 | 322 | mutex = threading.RLock() |
Pawel Zarembski |
0:01f31e923fe2 | 323 | terminate = False |
Pawel Zarembski |
0:01f31e923fe2 | 324 | error_msg_list = [] |
Pawel Zarembski |
0:01f31e923fe2 | 325 | |
Pawel Zarembski |
0:01f31e923fe2 | 326 | def _safe_print(message): |
Pawel Zarembski |
0:01f31e923fe2 | 327 | """Thread safe wrapper to print messages""" |
Pawel Zarembski |
0:01f31e923fe2 | 328 | with mutex: |
Pawel Zarembski |
0:01f31e923fe2 | 329 | print(message) |
Pawel Zarembski |
0:01f31e923fe2 | 330 | |
Pawel Zarembski |
0:01f31e923fe2 | 331 | def _test_msd(): |
Pawel Zarembski |
0:01f31e923fe2 | 332 | """MSD thread entry point for parallel testing""" |
Pawel Zarembski |
0:01f31e923fe2 | 333 | try: |
Pawel Zarembski |
0:01f31e923fe2 | 334 | _safe_print("msd started") |
Pawel Zarembski |
0:01f31e923fe2 | 335 | msd_data = msd.scsi_read10(100, 1) |
Pawel Zarembski |
0:01f31e923fe2 | 336 | while not terminate: |
Pawel Zarembski |
0:01f31e923fe2 | 337 | #msd_data = 'x' * 1024 * 16 # 16KB |
Pawel Zarembski |
0:01f31e923fe2 | 338 | msd.scsi_write10(100, msd_data) |
Pawel Zarembski |
0:01f31e923fe2 | 339 | _safe_print("msd end") |
Pawel Zarembski |
0:01f31e923fe2 | 340 | except: |
Pawel Zarembski |
0:01f31e923fe2 | 341 | error_msg_list.append("MSD test failed") |
Pawel Zarembski |
0:01f31e923fe2 | 342 | raise |
Pawel Zarembski |
0:01f31e923fe2 | 343 | |
Pawel Zarembski |
0:01f31e923fe2 | 344 | def _test_cdc(): |
Pawel Zarembski |
0:01f31e923fe2 | 345 | """CDC thread entry point for parallel testing""" |
Pawel Zarembski |
0:01f31e923fe2 | 346 | try: |
Pawel Zarembski |
0:01f31e923fe2 | 347 | _safe_print("cdc started") |
Pawel Zarembski |
0:01f31e923fe2 | 348 | while not terminate: |
Pawel Zarembski |
0:01f31e923fe2 | 349 | cdc.set_line_coding(115200) |
Pawel Zarembski |
0:01f31e923fe2 | 350 | cdc.get_line_coding() |
Pawel Zarembski |
0:01f31e923fe2 | 351 | cdc.send_break(cdc.SEND_BREAK_ON) |
Pawel Zarembski |
0:01f31e923fe2 | 352 | cdc.send_break(cdc.SEND_BREAK_OFF) |
Pawel Zarembski |
0:01f31e923fe2 | 353 | cdc.read(1024) |
Pawel Zarembski |
0:01f31e923fe2 | 354 | cdc.write("Hello world") |
Pawel Zarembski |
0:01f31e923fe2 | 355 | cdc.read(1024) |
Pawel Zarembski |
0:01f31e923fe2 | 356 | _safe_print("cdc end") |
Pawel Zarembski |
0:01f31e923fe2 | 357 | except: |
Pawel Zarembski |
0:01f31e923fe2 | 358 | error_msg_list.append("CDC test failed") |
Pawel Zarembski |
0:01f31e923fe2 | 359 | raise |
Pawel Zarembski |
0:01f31e923fe2 | 360 | |
Pawel Zarembski |
0:01f31e923fe2 | 361 | def _test_hid(): |
Pawel Zarembski |
0:01f31e923fe2 | 362 | """HID thread entry point for parallel testing""" |
Pawel Zarembski |
0:01f31e923fe2 | 363 | try: |
Pawel Zarembski |
0:01f31e923fe2 | 364 | _safe_print("hid started") |
Pawel Zarembski |
0:01f31e923fe2 | 365 | data = bytearray(64) |
Pawel Zarembski |
0:01f31e923fe2 | 366 | data[0] = 0x80 |
Pawel Zarembski |
0:01f31e923fe2 | 367 | while not terminate: |
Pawel Zarembski |
0:01f31e923fe2 | 368 | hid.set_report(data) |
Pawel Zarembski |
0:01f31e923fe2 | 369 | resp = hid.get_report(64) |
Pawel Zarembski |
0:01f31e923fe2 | 370 | assert resp[0] == 0x80 |
Pawel Zarembski |
0:01f31e923fe2 | 371 | _safe_print("hid end") |
Pawel Zarembski |
0:01f31e923fe2 | 372 | except: |
Pawel Zarembski |
0:01f31e923fe2 | 373 | error_msg_list.append("HID test failed") |
Pawel Zarembski |
0:01f31e923fe2 | 374 | raise |
Pawel Zarembski |
0:01f31e923fe2 | 375 | |
Pawel Zarembski |
0:01f31e923fe2 | 376 | thread_list = [] |
Pawel Zarembski |
0:01f31e923fe2 | 377 | for function in (_test_msd, _test_cdc, _test_hid): |
Pawel Zarembski |
0:01f31e923fe2 | 378 | thread = threading.Thread(target=function) |
Pawel Zarembski |
0:01f31e923fe2 | 379 | thread.start() |
Pawel Zarembski |
0:01f31e923fe2 | 380 | thread_list.append(thread) |
Pawel Zarembski |
0:01f31e923fe2 | 381 | |
Pawel Zarembski |
0:01f31e923fe2 | 382 | time.sleep(10) |
Pawel Zarembski |
0:01f31e923fe2 | 383 | |
Pawel Zarembski |
0:01f31e923fe2 | 384 | terminate = True |
Pawel Zarembski |
0:01f31e923fe2 | 385 | for thread in thread_list: |
Pawel Zarembski |
0:01f31e923fe2 | 386 | thread.join() |
Pawel Zarembski |
0:01f31e923fe2 | 387 | |
Pawel Zarembski |
0:01f31e923fe2 | 388 | for error in error_msg_list: |
Pawel Zarembski |
0:01f31e923fe2 | 389 | test_info.failure(error) |
Pawel Zarembski |
0:01f31e923fe2 | 390 | |
Pawel Zarembski |
0:01f31e923fe2 | 391 | |
Pawel Zarembski |
0:01f31e923fe2 | 392 | def _daplink_match(dev): |
Pawel Zarembski |
0:01f31e923fe2 | 393 | """DAPLink match function to be used with usb.core.find""" |
Pawel Zarembski |
0:01f31e923fe2 | 394 | try: |
Pawel Zarembski |
0:01f31e923fe2 | 395 | device_string = dev.product |
Pawel Zarembski |
0:01f31e923fe2 | 396 | except ValueError: |
Pawel Zarembski |
0:01f31e923fe2 | 397 | return False |
Pawel Zarembski |
0:01f31e923fe2 | 398 | if device_string is None: |
Pawel Zarembski |
0:01f31e923fe2 | 399 | return False |
Pawel Zarembski |
0:01f31e923fe2 | 400 | if device_string.find("CMSIS-DAP") < 0: |
Pawel Zarembski |
0:01f31e923fe2 | 401 | return False |
Pawel Zarembski |
0:01f31e923fe2 | 402 | return True |
Pawel Zarembski |
0:01f31e923fe2 | 403 | |
Pawel Zarembski |
0:01f31e923fe2 | 404 | |
Pawel Zarembski |
0:01f31e923fe2 | 405 | def _daplink_from_serial_number(serial_number): |
Pawel Zarembski |
0:01f31e923fe2 | 406 | """Return a usb handle to the DAPLink device with the serial number""" |
Pawel Zarembski |
0:01f31e923fe2 | 407 | dev_list = usb.core.find(find_all=True, custom_match=_daplink_match) |
Pawel Zarembski |
0:01f31e923fe2 | 408 | for dev in dev_list: |
Pawel Zarembski |
0:01f31e923fe2 | 409 | if dev.serial_number == serial_number: |
Pawel Zarembski |
0:01f31e923fe2 | 410 | return dev |
Pawel Zarembski |
0:01f31e923fe2 | 411 | return None |
Pawel Zarembski |
0:01f31e923fe2 | 412 | |
Pawel Zarembski |
0:01f31e923fe2 | 413 | |
Pawel Zarembski |
0:01f31e923fe2 | 414 | def _platform_supports_usb_test(): |
Pawel Zarembski |
0:01f31e923fe2 | 415 | """Return True if this platform supports USB testing, False otherwise""" |
Pawel Zarembski |
0:01f31e923fe2 | 416 | if os.name != "posix": |
Pawel Zarembski |
0:01f31e923fe2 | 417 | return False |
Pawel Zarembski |
0:01f31e923fe2 | 418 | if not hasattr(os, 'uname'): |
Pawel Zarembski |
0:01f31e923fe2 | 419 | if False: |
Pawel Zarembski |
0:01f31e923fe2 | 420 | # Hack to supress warnings for uname not existing |
Pawel Zarembski |
0:01f31e923fe2 | 421 | os.uname = lambda: [None] |
Pawel Zarembski |
0:01f31e923fe2 | 422 | return False |
Pawel Zarembski |
0:01f31e923fe2 | 423 | if os.uname()[0] == "Darwin": |
Pawel Zarembski |
0:01f31e923fe2 | 424 | return False |
Pawel Zarembski |
0:01f31e923fe2 | 425 | return True |
Pawel Zarembski |
0:01f31e923fe2 | 426 | |
Pawel Zarembski |
0:01f31e923fe2 | 427 | |
Pawel Zarembski |
0:01f31e923fe2 | 428 | def _set_usb_test_mode(hid, enabled): |
Pawel Zarembski |
0:01f31e923fe2 | 429 | """Set to True to enable USB testing mode""" |
Pawel Zarembski |
0:01f31e923fe2 | 430 | data = bytearray(64) |
Pawel Zarembski |
0:01f31e923fe2 | 431 | data[0] = 0x88 |
Pawel Zarembski |
0:01f31e923fe2 | 432 | data[1] = 1 if enabled else 0 |
Pawel Zarembski |
0:01f31e923fe2 | 433 | hid.set_report(data) |
Pawel Zarembski |
0:01f31e923fe2 | 434 | resp = hid.get_report(64) |
Pawel Zarembski |
0:01f31e923fe2 | 435 | if (resp[0] != 0x88) or (resp[1] != 1): |
Pawel Zarembski |
0:01f31e923fe2 | 436 | raise Exception("Error configuring USB test mode") |
Pawel Zarembski |
0:01f31e923fe2 | 437 | |
Pawel Zarembski |
0:01f31e923fe2 | 438 | |
Pawel Zarembski |
0:01f31e923fe2 | 439 | if __name__ == "__main__": |
Pawel Zarembski |
0:01f31e923fe2 | 440 | main() |