1/*-
2 * Copyright (c) 2007-2022 Hans Petter Selasky
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26#include <stdio.h>
27#include <stdint.h>
28#include <stdlib.h>
29#include <err.h>
30#include <string.h>
31#include <errno.h>
32#include <unistd.h>
33
34#include <sys/sysctl.h>
35#include <sys/time.h>
36
37#include <libusb20.h>
38#include <libusb20_desc.h>
39
40#include <dev/usb/usb_endian.h>
41
42#include "usbtest.h"
43
44#include "usb_msc_test.h"
45
46/* Command Block Wrapper */
47typedef struct {
48	uDWord	dCBWSignature;
49#define	CBWSIGNATURE	0x43425355
50	uDWord	dCBWTag;
51	uDWord	dCBWDataTransferLength;
52	uByte	bCBWFlags;
53#define	CBWFLAGS_OUT	0x00
54#define	CBWFLAGS_IN	0x80
55	uByte	bCBWLUN;
56	uByte	bCDBLength;
57#define	CBWCDBLENGTH	16
58	uByte	CBWCDB[CBWCDBLENGTH];
59} umass_bbb_cbw_t;
60
61#define	UMASS_BBB_CBW_SIZE	31
62
63/* Command Status Wrapper */
64typedef struct {
65	uDWord	dCSWSignature;
66#define	CSWSIGNATURE	0x53425355
67#define	CSWSIGNATURE_IMAGINATION_DBX1	0x43425355
68#define	CSWSIGNATURE_OLYMPUS_C1	0x55425355
69	uDWord	dCSWTag;
70	uDWord	dCSWDataResidue;
71	uByte	bCSWStatus;
72#define	CSWSTATUS_GOOD	0x0
73#define	CSWSTATUS_FAILED	0x1
74#define	CSWSTATUS_PHASE	0x2
75} umass_bbb_csw_t;
76
77#define	UMASS_BBB_CSW_SIZE	13
78
79#define	SC_READ_6			0x08
80#define	SC_READ_10			0x28
81#define	SC_READ_12			0xa8
82#define	SC_WRITE_6			0x0a
83#define	SC_WRITE_10			0x2a
84#define	SC_WRITE_12			0xaa
85
86static struct stats {
87	uint64_t xfer_error;
88	uint64_t xfer_success;
89	uint64_t xfer_reset;
90	uint64_t xfer_rx_bytes;
91	uint64_t xfer_tx_bytes;
92	uint64_t data_error;
93}	stats;
94
95static uint32_t xfer_current_id;
96static uint32_t xfer_wrapper_sig;
97static uint32_t block_size = 512;
98
99static struct libusb20_transfer *xfer_in;
100static struct libusb20_transfer *xfer_out;
101static struct libusb20_device *usb_pdev;
102static uint8_t usb_iface;
103static int sense_recurse;
104
105/*
106 * SCSI commands sniffed off the wire - LUN maybe needs to be
107 * adjusted!  Refer to "dev/usb/storage/ustorage_fs.c" for more
108 * information.
109 */
110static uint8_t mode_sense_6[0x6] = {0x1a, 0, 0x3f, 0, 0x0c};
111static uint8_t read_capacity[0xA] = {0x25,};
112static uint8_t request_sense[0xC] = {0x03, 0, 0, 0, 0x12};
113static uint8_t test_unit_ready[0x6] = {0};
114static uint8_t mode_page_inquiry[0x6] = {0x12, 1, 0x80, 0, 0xff, 0};
115static uint8_t request_invalid[0xC] = {0xEA, 0, 0, 0, 0};
116static uint8_t prevent_removal[0x6] = {0x1E, 0, 0, 0, 1};
117static uint8_t read_toc[0xA] = {0x43, 0x02, 0, 0, 0, 0xAA, 0, 0x0C};
118
119#define	TIMEOUT_FILTER(x) (x)
120
121static void usb_request_sense(uint8_t lun);
122
123static void
124do_msc_reset(uint8_t lun)
125{
126	struct LIBUSB20_CONTROL_SETUP_DECODED setup;
127
128	LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &setup);
129
130	setup.bmRequestType = LIBUSB20_REQUEST_TYPE_CLASS |
131	    LIBUSB20_RECIPIENT_INTERFACE;
132	setup.bRequest = 0xFF;		/* BBB reset */
133	setup.wValue = 0;
134	setup.wIndex = usb_iface;
135	setup.wLength = 0;
136
137	if (libusb20_dev_request_sync(usb_pdev, &setup, NULL, NULL, 5000, 0)) {
138		printf("ERROR: %s\n", __FUNCTION__);
139		stats.xfer_error++;
140	}
141	libusb20_tr_clear_stall_sync(xfer_in);
142	libusb20_tr_clear_stall_sync(xfer_out);
143
144	stats.xfer_reset++;
145
146	usb_request_sense(lun);
147}
148
149static uint8_t
150do_msc_cmd(uint8_t *pcmd, uint8_t cmdlen, void *pdata, uint32_t datalen,
151    uint8_t isread, uint8_t isshort, uint8_t lun, uint8_t flags)
152{
153	umass_bbb_cbw_t cbw;
154	umass_bbb_csw_t csw;
155	struct libusb20_transfer *xfer_io;
156	uint32_t actlen;
157	uint32_t timeout;
158	int error;
159
160	memset(&cbw, 0, sizeof(cbw));
161
162	USETDW(cbw.dCBWSignature, xfer_wrapper_sig);
163	USETDW(cbw.dCBWTag, xfer_current_id);
164	xfer_current_id++;
165	USETDW(cbw.dCBWDataTransferLength, datalen);
166	cbw.bCBWFlags = (isread ? CBWFLAGS_IN : CBWFLAGS_OUT);
167	cbw.bCBWLUN = lun;
168	cbw.bCDBLength = cmdlen;
169	bcopy(pcmd, cbw.CBWCDB, cmdlen);
170
171	actlen = 0;
172
173	timeout = ((datalen + 299999) / 300000) * 1000;
174	timeout += 5000;
175
176	if ((error = libusb20_tr_bulk_intr_sync(xfer_out,
177	    &cbw, sizeof(cbw), &actlen, TIMEOUT_FILTER(1000)))) {
178		printf("ERROR: CBW reception: %d\n", error);
179		do_msc_reset(lun);
180		return (1);
181	}
182	if (actlen != sizeof(cbw)) {
183		printf("ERROR: CBW length: %d != %d\n",
184		    actlen, (int)sizeof(cbw));
185		do_msc_reset(lun);
186		return (1);
187	}
188	if (flags & 1)
189		datalen /= 2;
190
191	if (datalen != 0) {
192		xfer_io = isread ? xfer_in : xfer_out;
193
194		if ((error = libusb20_tr_bulk_intr_sync(xfer_io,
195		    pdata, datalen, &actlen, TIMEOUT_FILTER(timeout)))) {
196			printf("ERROR: Data transfer: %d\n", error);
197			do_msc_reset(lun);
198			return (1);
199		}
200		if ((actlen != datalen) && (!isshort)) {
201			printf("ERROR: Short data: %d of %d bytes\n",
202			    actlen, datalen);
203			do_msc_reset(lun);
204			return (1);
205		}
206	}
207	actlen = 0;
208	timeout = 8;
209
210	do {
211		error = libusb20_tr_bulk_intr_sync(xfer_in, &csw,
212		    sizeof(csw), &actlen, TIMEOUT_FILTER(1000));
213		if (error) {
214			if (error == LIBUSB20_TRANSFER_TIMED_OUT) {
215				printf("TIMEOUT: Trying to get CSW again. "
216				    "%d tries left.\n", timeout);
217			} else {
218				break;
219			}
220		} else {
221			break;
222		}
223	} while (--timeout);
224
225	if (error) {
226		libusb20_tr_clear_stall_sync(xfer_in);
227		error = libusb20_tr_bulk_intr_sync(xfer_in, &csw,
228		    sizeof(csw), &actlen, TIMEOUT_FILTER(1000));
229		if (error) {
230			libusb20_tr_clear_stall_sync(xfer_in);
231			printf("ERROR: Could not read CSW: Stalled or "
232			    "timeout (%d).\n", error);
233			do_msc_reset(lun);
234			return (1);
235		}
236	}
237	if (UGETDW(csw.dCSWSignature) != CSWSIGNATURE) {
238		printf("ERROR: Wrong CSW signature\n");
239		do_msc_reset(lun);
240		return (1);
241	}
242	if (actlen != sizeof(csw)) {
243		printf("ERROR: Wrong CSW length: %d != %d\n",
244		    actlen, (int)sizeof(csw));
245		do_msc_reset(lun);
246		return (1);
247	}
248	if (csw.bCSWStatus != 0) {
249		printf("ERROR: CSW status: %d\n", (int)csw.bCSWStatus);
250		return (1);
251	} else {
252		stats.xfer_success++;
253		return (0);
254	}
255}
256
257static void
258do_msc_shorter_cmd(uint8_t lun)
259{
260	uint8_t buffer[sizeof(umass_bbb_cbw_t)];
261	int actlen;
262	int error;
263	int x;
264
265	memset(buffer, 0, sizeof(buffer));
266
267	for (x = 0; x != (sizeof(buffer) - 1); x++) {
268		error = libusb20_tr_bulk_intr_sync(xfer_out,
269		    buffer, x, &actlen, 250);
270
271		printf("Sent short %d of %d bytes wrapper block, "
272		    "status = %d\n", x, (int)(sizeof(buffer) - 1),
273		    error);
274
275		do_msc_reset(lun);
276
277		if (error != 0) {
278			printf("ERROR: Too short command wrapper "
279			    "was not accepted\n");
280			stats.xfer_error++;
281			break;
282		}
283	}
284}
285
286static uint8_t
287do_read_10(uint32_t lba, uint32_t len, void *buf, uint8_t lun)
288{
289	static uint8_t cmd[10];
290	uint8_t retval;
291
292	cmd[0] = SC_READ_10;
293
294	len /= block_size;
295
296	cmd[2] = lba >> 24;
297	cmd[3] = lba >> 16;
298	cmd[4] = lba >> 8;
299	cmd[5] = lba >> 0;
300
301	cmd[7] = len >> 8;
302	cmd[8] = len;
303
304	retval = do_msc_cmd(cmd, 10, buf, len * block_size, 1, 0, lun, 0);
305
306	if (retval) {
307		printf("ERROR: %s\n", __FUNCTION__);
308		stats.xfer_error++;
309	}
310	return (retval);
311}
312
313static uint8_t
314do_write_10(uint32_t lba, uint32_t len, void *buf, uint8_t lun)
315{
316	static uint8_t cmd[10];
317	uint8_t retval;
318	uint8_t abort;
319
320	cmd[0] = SC_WRITE_10;
321
322	abort = len & 1;
323
324	len /= block_size;
325
326	cmd[2] = lba >> 24;
327	cmd[3] = lba >> 16;
328	cmd[4] = lba >> 8;
329	cmd[5] = lba >> 0;
330
331	cmd[7] = len >> 8;
332	cmd[8] = len;
333
334	retval = do_msc_cmd(cmd, 10, buf, (len * block_size), 0, 0, lun, abort);
335
336	if (retval) {
337		printf("ERROR: %s\n", __FUNCTION__);
338		stats.xfer_error++;
339	}
340	return (retval);
341}
342
343static void
344do_io_test(struct usb_msc_params *p, uint8_t lun, uint32_t lba_max,
345    uint8_t *buffer, uint8_t *reference)
346{
347	uint32_t io_offset;
348	uint32_t io_size;
349	uint32_t temp;
350	uint8_t do_read;
351	uint8_t retval;
352
353	switch (p->io_mode) {
354	case USB_MSC_IO_MODE_WRITE_ONLY:
355		do_read = 0;
356		break;
357	case USB_MSC_IO_MODE_READ_WRITE:
358		do_read = (usb_ts_rand_noise() & 1);
359		break;
360	default:
361		do_read = 1;
362		break;
363	}
364
365	switch (p->io_offset) {
366	case USB_MSC_IO_OFF_RANDOM:
367		io_offset = usb_ts_rand_noise();
368		break;
369	default:
370		io_offset = 0;
371		break;
372	}
373
374	switch (p->io_delay) {
375	case USB_MSC_IO_DELAY_RANDOM_10MS:
376		usleep(((uint32_t)usb_ts_rand_noise()) % 10000U);
377		break;
378	case USB_MSC_IO_DELAY_RANDOM_100MS:
379		usleep(((uint32_t)usb_ts_rand_noise()) % 100000U);
380		break;
381	case USB_MSC_IO_DELAY_FIXED_10MS:
382		usleep(10000);
383		break;
384	case USB_MSC_IO_DELAY_FIXED_100MS:
385		usleep(100000);
386		break;
387	default:
388		break;
389	}
390
391	switch (p->io_size) {
392	case USB_MSC_IO_SIZE_RANDOM:
393		io_size = ((uint32_t)usb_ts_rand_noise()) & 65535U;
394		break;
395	case USB_MSC_IO_SIZE_INCREASING:
396		io_size = (xfer_current_id & 65535U);
397		break;
398	case USB_MSC_IO_SIZE_FIXED_1BLK:
399		io_size = 1;
400		break;
401	case USB_MSC_IO_SIZE_FIXED_2BLK:
402		io_size = 2;
403		break;
404	case USB_MSC_IO_SIZE_FIXED_4BLK:
405		io_size = 4;
406		break;
407	case USB_MSC_IO_SIZE_FIXED_8BLK:
408		io_size = 8;
409		break;
410	case USB_MSC_IO_SIZE_FIXED_16BLK:
411		io_size = 16;
412		break;
413	case USB_MSC_IO_SIZE_FIXED_32BLK:
414		io_size = 32;
415		break;
416	case USB_MSC_IO_SIZE_FIXED_64BLK:
417		io_size = 64;
418		break;
419	case USB_MSC_IO_SIZE_FIXED_128BLK:
420		io_size = 128;
421		break;
422	case USB_MSC_IO_SIZE_FIXED_256BLK:
423		io_size = 256;
424		break;
425	case USB_MSC_IO_SIZE_FIXED_512BLK:
426		io_size = 512;
427		break;
428	case USB_MSC_IO_SIZE_FIXED_1024BLK:
429		io_size = 1024;
430		break;
431	default:
432		io_size = 1;
433		break;
434	}
435
436	if (io_size == 0)
437		io_size = 1;
438
439	io_offset %= lba_max;
440
441	temp = (lba_max - io_offset);
442
443	if (io_size > temp)
444		io_size = temp;
445
446	if (do_read) {
447		retval = do_read_10(io_offset, io_size * block_size,
448		    buffer + (io_offset * block_size), lun);
449
450		if (retval == 0) {
451			if (bcmp(buffer + (io_offset * block_size),
452			    reference + (io_offset * block_size),
453			    io_size * block_size)) {
454				printf("ERROR: Data comparison failure\n");
455				stats.data_error++;
456				retval = 1;
457			}
458		}
459		stats.xfer_rx_bytes += (io_size * block_size);
460
461	} else {
462
463		retval = do_write_10(io_offset, io_size * block_size,
464		    reference + (io_offset * block_size), lun);
465
466		stats.xfer_tx_bytes += (io_size * block_size);
467	}
468
469	if ((stats.xfer_error + stats.data_error +
470	    stats.xfer_reset) >= p->max_errors) {
471		printf("Maximum number of errors exceeded\n");
472		p->done = 1;
473	}
474}
475
476static void
477usb_request_sense(uint8_t lun)
478{
479	uint8_t dummy_buf[255];
480
481	if (sense_recurse)
482		return;
483
484	sense_recurse++;
485
486	do_msc_cmd(request_sense, sizeof(request_sense),
487	    dummy_buf, 255, 1, 1, lun, 0);
488
489	sense_recurse--;
490}
491
492static void
493usb_msc_test(struct usb_msc_params *p)
494{
495	struct stats last_stat;
496	struct timeval sub_tv;
497	struct timeval ref_tv;
498	struct timeval res_tv;
499	uint8_t *buffer = NULL;
500	uint8_t *reference = NULL;
501	uint32_t dummy_buf[65536 / 4];
502	uint32_t lba_max;
503	uint32_t x;
504	uint32_t y;
505	uint32_t capacity_lba;
506	uint32_t capacity_bs;
507	time_t last_sec;
508	uint8_t lun;
509	int tries;
510
511	memset(&last_stat, 0, sizeof(last_stat));
512
513	switch (p->io_lun) {
514	case USB_MSC_IO_LUN_0:
515		lun = 0;
516		break;
517	case USB_MSC_IO_LUN_1:
518		lun = 1;
519		break;
520	case USB_MSC_IO_LUN_2:
521		lun = 2;
522		break;
523	case USB_MSC_IO_LUN_3:
524		lun = 3;
525		break;
526	default:
527		lun = 0;
528		break;
529	}
530
531	p->done = 0;
532
533	sense_recurse = p->try_sense_on_error ? 0 : 1;
534
535	printf("Resetting device ...\n");
536
537	do_msc_reset(lun);
538
539	printf("Testing SCSI commands ...\n");
540
541	if (p->try_all_lun) {
542		printf("Requesting sense from LUN 0..255 ... ");
543		for (x = y = 0; x != 256; x++) {
544			if (do_msc_cmd(mode_sense_6, sizeof(mode_sense_6),
545			    dummy_buf, 255, 1, 1, x, 0))
546				y++;
547
548			if (libusb20_dev_check_connected(usb_pdev) != 0) {
549				printf(" disconnect ");
550				break;
551			}
552		}
553		printf("Passed=%d, Failed=%d\n", 256 - y, y);
554	}
555	do_msc_cmd(mode_sense_6, sizeof(mode_sense_6),
556	    dummy_buf, 255, 1, 1, lun, 0);
557	do_msc_cmd(request_sense, sizeof(request_sense),
558	    dummy_buf, 255, 1, 1, lun, 0);
559
560	for (tries = 0; tries != 4; tries++) {
561
562		memset(dummy_buf, 0, sizeof(dummy_buf));
563
564		if (do_msc_cmd(read_capacity, sizeof(read_capacity),
565		    dummy_buf, 255, 1, 1, lun, 0) != 0) {
566			printf("Cannot read disk capacity (%u / 4)\n", tries);
567			if (tries == 3)
568				return;
569			usleep(50000);
570			continue;
571		} else {
572			break;
573		}
574	}
575
576	capacity_lba = be32toh(dummy_buf[0]);
577	capacity_bs = be32toh(dummy_buf[1]);
578
579	printf("Disk reports a capacity of LBA=%u and BS=%u\n",
580	    capacity_lba, capacity_bs);
581
582	block_size = capacity_bs;
583
584	if (capacity_bs > 65535) {
585		printf("Blocksize is too big\n");
586		return;
587	}
588	if (capacity_bs < 1) {
589		printf("Blocksize is too small\n");
590		return;
591	}
592	if (capacity_bs != 512)
593		printf("INFO: Blocksize is not 512 bytes\n");
594
595	if (p->try_shorter_wrapper_block) {
596		printf("Trying too short command wrapper:\n");
597		do_msc_shorter_cmd(lun);
598	}
599
600	if (p->try_invalid_scsi_command) {
601		int status;
602
603		for (tries = 0; tries != 4; tries++) {
604
605			printf("Trying invalid SCSI command: ");
606
607			status = do_msc_cmd(request_invalid,
608			    sizeof(request_invalid), dummy_buf,
609			    255, 1, 1, lun, 0);
610
611			printf("Result%s as expected\n", status ? "" : " NOT");
612
613			usleep(50000);
614		}
615	}
616	if (p->try_invalid_wrapper_block) {
617		int status;
618
619		for (tries = 0; tries != 4; tries++) {
620
621			printf("Trying invalid USB wrapper block signature: ");
622
623			xfer_wrapper_sig = 0x55663322;
624
625			status = do_msc_cmd(read_capacity,
626			    sizeof(read_capacity), dummy_buf,
627			    255, 1, 1, lun, 0);
628
629			printf("Result%s as expected\n", status ? "" : " NOT");
630
631			xfer_wrapper_sig = CBWSIGNATURE;
632
633			usleep(50000);
634		}
635	}
636	do_msc_cmd(request_sense, sizeof(request_sense), dummy_buf, 255, 1, 1, lun, 0);
637	do_msc_cmd(read_capacity, sizeof(read_capacity), dummy_buf, 255, 1, 1, lun, 0);
638	do_msc_cmd(request_sense, sizeof(request_sense), dummy_buf, 255, 1, 1, lun, 0);
639	do_msc_cmd(test_unit_ready, sizeof(test_unit_ready), 0, 0, 1, 1, lun, 0);
640	do_msc_cmd(test_unit_ready, sizeof(test_unit_ready), 0, 0, 1, 1, lun, 0);
641	do_msc_cmd(request_sense, sizeof(request_sense), dummy_buf, 255, 1, 1, lun, 0);
642	do_msc_cmd(test_unit_ready, sizeof(test_unit_ready), 0, 0, 1, 1, lun, 0);
643	do_msc_cmd(request_sense, sizeof(request_sense), dummy_buf, 255, 1, 1, lun, 0);
644	do_msc_cmd(test_unit_ready, sizeof(test_unit_ready), 0, 0, 1, 1, lun, 0);
645	do_msc_cmd(test_unit_ready, sizeof(test_unit_ready), 0, 0, 1, 1, lun, 0);
646	do_msc_cmd(test_unit_ready, sizeof(test_unit_ready), 0, 0, 1, 1, lun, 0);
647	do_msc_cmd(request_sense, sizeof(request_sense), dummy_buf, 255, 1, 1, lun, 0);
648	do_msc_cmd(test_unit_ready, sizeof(test_unit_ready), 0, 0, 1, 1, lun, 0);
649	do_msc_cmd(read_capacity, sizeof(read_capacity), dummy_buf, 255, 1, 1, lun, 0);
650	do_msc_cmd(mode_page_inquiry, sizeof(mode_page_inquiry), dummy_buf, 255, 1, 1, lun, 0);
651	do_msc_cmd(mode_page_inquiry, sizeof(mode_page_inquiry), dummy_buf, 255, 1, 1, lun, 0);
652
653	if (do_msc_cmd(prevent_removal, sizeof(prevent_removal),
654	    0, 0, 1, 1, lun, 0)) {
655		printf("INFO: Prevent medium removal failed\n");
656	}
657	if (do_msc_cmd(read_toc, sizeof(read_toc),
658	    dummy_buf, 255, 1, 1, lun, 0)) {
659		printf("INFO: Read Table Of Content failed\n");
660	}
661	if (p->try_last_lba) {
662
663		for (y = 0, x = (1UL << 31); x; x >>= 1) {
664			if (do_read_10(x | y, block_size, dummy_buf, lun) == 0)
665				y |= x;
666		}
667
668		printf("Highest readable LBA: %u (%s), "
669		    "Capacity is %u MBytes\n", y,
670		    (capacity_lba != y) ? "WRONG" : "OK",
671		    (int)((((uint64_t)(y) * (uint64_t)block_size) +
672		    (uint64_t)block_size) / 1000000ULL));
673	} else {
674
675		y = capacity_lba;
676
677		printf("Highest readable LBA: %u (not "
678		    "verified), Capacity is %u MBytes\n", y,
679		    (int)((((uint64_t)(y) * (uint64_t)block_size) +
680		    (uint64_t)block_size) / 1000000ULL));
681	}
682
683	if (y != 0xFFFFFFFFU)
684		y++;
685
686	lba_max = y;
687
688	switch (p->io_area) {
689	case USB_MSC_IO_AREA_1MB:
690		lba_max = 1024;
691		break;
692	case USB_MSC_IO_AREA_16MB:
693		lba_max = 1024 * 16;
694		break;
695	case USB_MSC_IO_AREA_256MB:
696		lba_max = 1024 * 256;
697		break;
698	case USB_MSC_IO_AREA_COMPLETE:
699	default:
700		break;
701	}
702
703	if (lba_max > 65535)
704		lba_max = 65535;
705
706	printf("Highest testable LBA: %u\n", (int)lba_max);
707
708	buffer = malloc(block_size * lba_max);
709	if (buffer == NULL) {
710		printf("ERROR: Could not allocate memory\n");
711		goto fail;
712	}
713	reference = malloc(block_size * lba_max);
714	if (reference == NULL) {
715		printf("ERROR: Could not allocate memory\n");
716		goto fail;
717	}
718retry_read_init:
719
720	printf("Setting up initial data pattern, "
721	    "LBA limit = %u ... ", lba_max);
722
723	switch (p->io_mode) {
724	case USB_MSC_IO_MODE_WRITE_ONCE_READ_ONLY:
725	case USB_MSC_IO_MODE_WRITE_ONLY:
726	case USB_MSC_IO_MODE_READ_WRITE:
727
728		switch (p->io_pattern) {
729		case USB_MSC_IO_PATTERN_FIXED:
730			for (x = 0; x != (block_size * lba_max); x += 8) {
731				reference[x + 0] = x >> 24;
732				reference[x + 1] = x >> 16;
733				reference[x + 2] = x >> 8;
734				reference[x + 3] = x >> 0;
735				reference[x + 4] = 0xFF;
736				reference[x + 5] = 0x00;
737				reference[x + 6] = 0xFF;
738				reference[x + 7] = 0x00;
739			}
740			if (do_write_10(0, lba_max * block_size,
741			    reference, lun)) {
742				printf("FAILED\n");
743				lba_max /= 2;
744				if (lba_max)
745					goto retry_read_init;
746				goto fail;
747			}
748			printf("SUCCESS\n");
749			break;
750		case USB_MSC_IO_PATTERN_RANDOM:
751			for (x = 0; x != (block_size * lba_max); x++) {
752				reference[x] = usb_ts_rand_noise() % 255U;
753			}
754			if (do_write_10(0, lba_max * block_size,
755			    reference, lun)) {
756				printf("FAILED\n");
757				lba_max /= 2;
758				if (lba_max)
759					goto retry_read_init;
760				goto fail;
761			}
762			printf("SUCCESS\n");
763			break;
764		default:
765			if (do_read_10(0, lba_max * block_size,
766			    reference, lun)) {
767				printf("FAILED\n");
768				lba_max /= 2;
769				if (lba_max)
770					goto retry_read_init;
771				goto fail;
772			}
773			printf("SUCCESS\n");
774			break;
775		}
776		break;
777
778	default:
779		if (do_read_10(0, lba_max * block_size, reference, lun)) {
780			printf("FAILED\n");
781			lba_max /= 2;
782			if (lba_max)
783				goto retry_read_init;
784			goto fail;
785		}
786		printf("SUCCESS\n");
787		break;
788	}
789
790
791	if (p->try_abort_data_write) {
792		if (do_write_10(0, (2 * block_size) | 1, reference, lun))
793			printf("Aborted data write failed (OK)!\n");
794		else
795			printf("Aborted data write did not fail (ERROR)!\n");
796
797		if (do_read_10(0, (2 * block_size), reference, lun))
798			printf("Post-aborted data read failed (ERROR)\n");
799		else
800			printf("Post-aborted data read success (OK)!\n");
801	}
802	printf("Starting test ...\n");
803
804	gettimeofday(&ref_tv, 0);
805
806	last_sec = ref_tv.tv_sec;
807
808	printf("\n");
809
810	while (1) {
811
812		gettimeofday(&sub_tv, 0);
813
814		if (last_sec != sub_tv.tv_sec) {
815
816			printf("STATUS: ID=%u, RX=%u bytes/sec, "
817			    "TX=%u bytes/sec, ERR=%u, RST=%u, DERR=%u\n",
818			    (int)xfer_current_id,
819			    (int)(stats.xfer_rx_bytes -
820			    last_stat.xfer_rx_bytes),
821			    (int)(stats.xfer_tx_bytes -
822			    last_stat.xfer_tx_bytes),
823			    (int)(stats.xfer_error),
824			    (int)(stats.xfer_reset),
825			    (int)(stats.data_error));
826
827			fflush(stdout);
828
829			last_sec = sub_tv.tv_sec;
830			last_stat = stats;
831		}
832		timersub(&sub_tv, &ref_tv, &res_tv);
833
834		if ((res_tv.tv_sec < 0) || (res_tv.tv_sec >= (int)p->duration))
835			break;
836
837		do_io_test(p, lun, lba_max, buffer, reference);
838
839		if (libusb20_dev_check_connected(usb_pdev) != 0) {
840			printf("Device disconnected\n");
841			break;
842		}
843		if (p->done) {
844			printf("Maximum number of errors exceeded\n");
845			break;
846		}
847	}
848
849	printf("\nTest done!\n");
850
851fail:
852	if (buffer)
853		free(buffer);
854	if (reference)
855		free(reference);
856}
857
858void
859show_host_device_selection(uint8_t level, struct uaddr *puaddr)
860{
861	struct libusb20_backend *pbe;
862	struct libusb20_device *pdev;
863	struct LIBUSB20_DEVICE_DESC_DECODED *ddesc;
864
865	struct uaddr uaddr[USB_DEVICES_MAX];
866
867	int index;
868	int sel;
869
870	const char *ptr;
871
872top:
873	pbe = libusb20_be_alloc_default();
874	pdev = NULL;
875	index = 0;
876
877	printf("\n[] Select USB device:\n");
878
879	while ((pdev = libusb20_be_device_foreach(pbe, pdev))) {
880
881		if (libusb20_dev_get_mode(pdev) != LIBUSB20_MODE_HOST)
882			continue;
883
884		if (index < USB_DEVICES_MAX) {
885			ddesc = libusb20_dev_get_device_desc(pdev);
886			ptr = libusb20_dev_get_desc(pdev);
887			printf("%s%d) %s\n", indent[level], index, ptr);
888			uaddr[index].vid = ddesc->idVendor;
889			uaddr[index].pid = ddesc->idProduct;
890			uaddr[index].bus = libusb20_dev_get_bus_number(pdev);
891			uaddr[index].addr = libusb20_dev_get_address(pdev);
892			index++;
893		} else {
894			break;
895		}
896	}
897
898	printf("%sr) Refresh device list\n", indent[level]);
899	printf("%sx) Return to previous menu\n", indent[level]);
900
901	/* release data */
902	libusb20_be_free(pbe);
903
904	sel = get_integer();
905
906	if (sel == -2)
907		goto top;
908
909	if ((sel < 0) || (sel >= index)) {
910		memset(puaddr, 0, sizeof(*puaddr));
911	} else {
912		*puaddr = uaddr[sel];
913	}
914}
915
916struct libusb20_device *
917find_usb_device(struct uaddr uaddr)
918{
919	struct libusb20_backend *pbe = libusb20_be_alloc_default();
920	struct libusb20_device *pdev = NULL;
921	struct LIBUSB20_DEVICE_DESC_DECODED *ddesc;
922
923	while ((pdev = libusb20_be_device_foreach(pbe, pdev))) {
924
925		if (libusb20_dev_get_mode(pdev) != LIBUSB20_MODE_HOST)
926			continue;
927
928		ddesc = libusb20_dev_get_device_desc(pdev);
929
930		if ((uaddr.vid == ddesc->idVendor) &&
931		    (uaddr.pid == ddesc->idProduct) &&
932		    (uaddr.addr == 0 ||
933		     (uaddr.addr == libusb20_dev_get_address(pdev) &&
934		      uaddr.bus == libusb20_dev_get_bus_number(pdev)))) {
935			libusb20_be_dequeue_device(pbe, pdev);
936			break;
937		}
938	}
939
940	/* release data */
941	libusb20_be_free(pbe);
942
943	return (pdev);
944}
945
946void
947find_usb_endpoints(struct libusb20_device *pdev, uint8_t class,
948    uint8_t subclass, uint8_t protocol, uint8_t alt_setting,
949    uint8_t *pif, uint8_t *in_ep, uint8_t *out_ep, uint8_t next_if)
950{
951	struct libusb20_config *pcfg;
952	struct libusb20_interface *iface;
953	struct libusb20_endpoint *ep;
954	uint8_t x;
955	uint8_t y;
956	uint8_t z;
957
958	*in_ep = 0;
959	*out_ep = 0;
960	*pif = 0;
961
962	pcfg = libusb20_dev_alloc_config(pdev,
963	    libusb20_dev_get_config_index(pdev));
964
965	if (pcfg == NULL)
966		return;
967
968	for (x = 0; x != pcfg->num_interface; x++) {
969
970		y = alt_setting;
971
972		iface = (pcfg->interface + x);
973
974		if ((iface->desc.bInterfaceClass == class) &&
975		    (iface->desc.bInterfaceSubClass == subclass ||
976		    subclass == 255) &&
977		    (iface->desc.bInterfaceProtocol == protocol ||
978		    protocol == 255)) {
979
980			if (next_if) {
981				x++;
982				if (x == pcfg->num_interface)
983					break;
984				iface = (pcfg->interface + x);
985			}
986			*pif = x;
987
988			for (z = 0; z != iface->num_endpoints; z++) {
989				ep = iface->endpoints + z;
990
991				/* BULK only */
992				if ((ep->desc.bmAttributes & 3) != 2)
993					continue;
994
995				if (ep->desc.bEndpointAddress & 0x80)
996					*in_ep = ep->desc.bEndpointAddress;
997				else
998					*out_ep = ep->desc.bEndpointAddress;
999			}
1000			break;
1001		}
1002	}
1003
1004	free(pcfg);
1005}
1006
1007static void
1008exec_host_msc_test(struct usb_msc_params *p, struct uaddr uaddr)
1009{
1010	struct libusb20_device *pdev;
1011
1012	uint8_t in_ep;
1013	uint8_t out_ep;
1014	uint8_t iface;
1015
1016	int error;
1017
1018	memset(&stats, 0, sizeof(stats));
1019
1020	xfer_current_id = 0;
1021	xfer_wrapper_sig = CBWSIGNATURE;
1022
1023	pdev = find_usb_device(uaddr);
1024	if (pdev == NULL) {
1025		printf("USB device not found\n");
1026		return;
1027	}
1028	find_usb_endpoints(pdev, 8, 6, 0x50, 0, &iface, &in_ep, &out_ep, 0);
1029
1030	if ((in_ep == 0) || (out_ep == 0)) {
1031		printf("Could not find USB endpoints\n");
1032		libusb20_dev_free(pdev);
1033		return;
1034	}
1035	printf("Attaching to: %s @ iface %d\n",
1036	    libusb20_dev_get_desc(pdev), iface);
1037
1038	if (libusb20_dev_open(pdev, 2)) {
1039		printf("Could not open USB device\n");
1040		libusb20_dev_free(pdev);
1041		return;
1042	}
1043	if (libusb20_dev_detach_kernel_driver(pdev, iface)) {
1044		printf("WARNING: Could not detach kernel driver\n");
1045	}
1046	xfer_in = libusb20_tr_get_pointer(pdev, 0);
1047	error = libusb20_tr_open(xfer_in, 65536, 1, in_ep);
1048	if (error) {
1049		printf("Could not open USB endpoint %d\n", in_ep);
1050		libusb20_dev_free(pdev);
1051		return;
1052	}
1053	xfer_out = libusb20_tr_get_pointer(pdev, 1);
1054	error = libusb20_tr_open(xfer_out, 65536, 1, out_ep);
1055	if (error) {
1056		printf("Could not open USB endpoint %d\n", out_ep);
1057		libusb20_dev_free(pdev);
1058		return;
1059	}
1060	usb_pdev = pdev;
1061	usb_iface = iface;
1062
1063	usb_msc_test(p);
1064
1065	libusb20_dev_free(pdev);
1066}
1067
1068static void
1069set_defaults(struct usb_msc_params *p)
1070{
1071	memset(p, 0, sizeof(*p));
1072
1073	p->duration = 60;		/* seconds */
1074	p->try_invalid_scsi_command = 1;
1075	p->try_invalid_wrapper_block = 1;
1076	p->try_last_lba = 1;
1077	p->max_errors = -1;
1078}
1079
1080static const char *
1081get_io_mode(const struct usb_msc_params *p)
1082{
1083	;				/* indent fix */
1084	switch (p->io_mode) {
1085	case USB_MSC_IO_MODE_READ_ONLY:
1086		return ("Read Only");
1087	case USB_MSC_IO_MODE_WRITE_ONCE_READ_ONLY:
1088		return ("Write Once, Read Only");
1089	case USB_MSC_IO_MODE_WRITE_ONLY:
1090		return ("Write Only");
1091	case USB_MSC_IO_MODE_READ_WRITE:
1092		return ("Read and Write");
1093	default:
1094		return ("Unknown");
1095	}
1096}
1097
1098static const char *
1099get_io_pattern(const struct usb_msc_params *p)
1100{
1101	;				/* indent fix */
1102	switch (p->io_pattern) {
1103	case USB_MSC_IO_PATTERN_FIXED:
1104		return ("Fixed");
1105	case USB_MSC_IO_PATTERN_RANDOM:
1106		return ("Random");
1107	case USB_MSC_IO_PATTERN_PRESERVE:
1108		return ("Preserve");
1109	default:
1110		return ("Unknown");
1111	}
1112}
1113
1114static const char *
1115get_io_size(const struct usb_msc_params *p)
1116{
1117	;				/* indent fix */
1118	switch (p->io_size) {
1119	case USB_MSC_IO_SIZE_RANDOM:
1120		return ("Random");
1121	case USB_MSC_IO_SIZE_INCREASING:
1122		return ("Increasing");
1123	case USB_MSC_IO_SIZE_FIXED_1BLK:
1124		return ("Single block");
1125	case USB_MSC_IO_SIZE_FIXED_2BLK:
1126		return ("2 blocks");
1127	case USB_MSC_IO_SIZE_FIXED_4BLK:
1128		return ("4 blocks");
1129	case USB_MSC_IO_SIZE_FIXED_8BLK:
1130		return ("8 blocks");
1131	case USB_MSC_IO_SIZE_FIXED_16BLK:
1132		return ("16 blocks");
1133	case USB_MSC_IO_SIZE_FIXED_32BLK:
1134		return ("32 blocks");
1135	case USB_MSC_IO_SIZE_FIXED_64BLK:
1136		return ("64 blocks");
1137	case USB_MSC_IO_SIZE_FIXED_128BLK:
1138		return ("128 blocks");
1139	case USB_MSC_IO_SIZE_FIXED_256BLK:
1140		return ("256 blocks");
1141	case USB_MSC_IO_SIZE_FIXED_512BLK:
1142		return ("512 blocks");
1143	case USB_MSC_IO_SIZE_FIXED_1024BLK:
1144		return ("1024 blocks");
1145	default:
1146		return ("Unknown");
1147	}
1148}
1149
1150static const char *
1151get_io_delay(const struct usb_msc_params *p)
1152{
1153	;				/* indent fix */
1154	switch (p->io_delay) {
1155	case USB_MSC_IO_DELAY_NONE:
1156		return ("None");
1157	case USB_MSC_IO_DELAY_RANDOM_10MS:
1158		return ("Random 10ms");
1159	case USB_MSC_IO_DELAY_RANDOM_100MS:
1160		return ("Random 100ms");
1161	case USB_MSC_IO_DELAY_FIXED_10MS:
1162		return ("Fixed 10ms");
1163	case USB_MSC_IO_DELAY_FIXED_100MS:
1164		return ("Fixed 100ms");
1165	default:
1166		return ("Unknown");
1167	}
1168}
1169
1170static const char *
1171get_io_offset(const struct usb_msc_params *p)
1172{
1173	;				/* indent fix */
1174	switch (p->io_offset) {
1175	case USB_MSC_IO_OFF_START_OF_DISK:
1176		return ("Start Of Disk");
1177	case USB_MSC_IO_OFF_RANDOM:
1178		return ("Random Offset");
1179	default:
1180		return ("Unknown");
1181	}
1182}
1183
1184static const char *
1185get_io_area(const struct usb_msc_params *p)
1186{
1187	;				/* indent fix */
1188	switch (p->io_area) {
1189	case USB_MSC_IO_AREA_COMPLETE:
1190		return ("Complete Disk");
1191	case USB_MSC_IO_AREA_1MB:
1192		return ("First MegaByte");
1193	case USB_MSC_IO_AREA_16MB:
1194		return ("First 16 MegaBytes");
1195	case USB_MSC_IO_AREA_256MB:
1196		return ("First 256 MegaBytes");
1197	default:
1198		return ("Unknown");
1199	}
1200}
1201
1202void
1203show_host_msc_test(uint8_t level, struct uaddr uaddr, uint32_t duration)
1204{
1205	struct usb_msc_params params;
1206	uint8_t retval;
1207
1208	set_defaults(&params);
1209
1210	params.duration = duration;
1211
1212	while (1) {
1213
1214		retval = usb_ts_show_menu(level,
1215		    "Mass Storage Test Parameters",
1216		    " 1) Toggle I/O mode: <%s>\n"
1217		    " 2) Toggle I/O size: <%s>\n"
1218		    " 3) Toggle I/O delay: <%s>\n"
1219		    " 4) Toggle I/O offset: <%s>\n"
1220		    " 5) Toggle I/O area: <%s>\n"
1221		    " 6) Toggle I/O pattern: <%s>\n"
1222		    " 7) Toggle try invalid SCSI command: <%s>\n"
1223		    " 8) Toggle try invalid wrapper block: <%s>\n"
1224		    " 9) Toggle try invalid MaxPacketSize: <%s>\n"
1225		    "10) Toggle try last Logical Block Address: <%s>\n"
1226		    "11) Toggle I/O lun: <%d>\n"
1227		    "12) Set maximum number of errors: <%d>\n"
1228		    "13) Set test duration: <%d> seconds\n"
1229		    "14) Toggle try aborted write transfer: <%s>\n"
1230		    "15) Toggle request sense on error: <%s>\n"
1231		    "16) Toggle try all LUN: <%s>\n"
1232		    "17) Toggle try too short wrapper block: <%s>\n"
1233		    "20) Reset parameters\n"
1234		    "30) Start test (VID=0x%04x, PID=0x%04x)\n"
1235		    "40) Select another device\n"
1236		    " x) Return to previous menu \n",
1237		    get_io_mode(&params),
1238		    get_io_size(&params),
1239		    get_io_delay(&params),
1240		    get_io_offset(&params),
1241		    get_io_area(&params),
1242		    get_io_pattern(&params),
1243		    (params.try_invalid_scsi_command ? "YES" : "NO"),
1244		    (params.try_invalid_wrapper_block ? "YES" : "NO"),
1245		    (params.try_invalid_max_packet_size ? "YES" : "NO"),
1246		    (params.try_last_lba ? "YES" : "NO"),
1247		    params.io_lun,
1248		    (int)params.max_errors,
1249		    (int)params.duration,
1250		    (params.try_abort_data_write ? "YES" : "NO"),
1251		    (params.try_sense_on_error ? "YES" : "NO"),
1252		    (params.try_all_lun ? "YES" : "NO"),
1253		    (params.try_shorter_wrapper_block ? "YES" : "NO"),
1254		    uaddr.vid, uaddr.pid);
1255		switch (retval) {
1256		case 0:
1257			break;
1258		case 1:
1259			params.io_mode++;
1260			params.io_mode %= USB_MSC_IO_MODE_MAX;
1261			break;
1262		case 2:
1263			params.io_size++;
1264			params.io_size %= USB_MSC_IO_SIZE_MAX;
1265			break;
1266		case 3:
1267			params.io_delay++;
1268			params.io_delay %= USB_MSC_IO_DELAY_MAX;
1269			break;
1270		case 4:
1271			params.io_offset++;
1272			params.io_offset %= USB_MSC_IO_OFF_MAX;
1273			break;
1274		case 5:
1275			params.io_area++;
1276			params.io_area %= USB_MSC_IO_AREA_MAX;
1277			break;
1278		case 6:
1279			params.io_pattern++;
1280			params.io_pattern %= USB_MSC_IO_PATTERN_MAX;
1281			break;
1282		case 7:
1283			params.try_invalid_scsi_command ^= 1;
1284			break;
1285		case 8:
1286			params.try_invalid_wrapper_block ^= 1;
1287			break;
1288		case 9:
1289			params.try_invalid_max_packet_size ^= 1;
1290			break;
1291		case 10:
1292			params.try_last_lba ^= 1;
1293			break;
1294		case 11:
1295			params.io_lun++;
1296			params.io_lun %= USB_MSC_IO_LUN_MAX;
1297			break;
1298		case 12:
1299			params.max_errors = get_integer();
1300			break;
1301		case 13:
1302			params.duration = get_integer();
1303			break;
1304		case 14:
1305			params.try_abort_data_write ^= 1;
1306			break;
1307		case 15:
1308			params.try_sense_on_error ^= 1;
1309			break;
1310		case 16:
1311			params.try_all_lun ^= 1;
1312			break;
1313		case 17:
1314			params.try_shorter_wrapper_block ^= 1;
1315			break;
1316		case 20:
1317			set_defaults(&params);
1318			break;
1319		case 30:
1320			exec_host_msc_test(&params, uaddr);
1321			break;
1322		case 40:
1323			show_host_device_selection(level + 1, &uaddr);
1324			break;
1325		default:
1326			return;
1327		}
1328	}
1329}
1330