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