xref: /dragonfly/tools/tools/usbtest/usb_msc_test.c (revision 129a2703e7ed2e24dc71522208dff92452c925db)
1 /* $FreeBSD: head/tools/tools/usbtest/usb_msc_test.c 260587 2014-01-13 13:27:00Z hselasky $ */
2 /*-
3  * Copyright (c) 2007-2012 Hans Petter Selasky. All rights reserved.
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 <bus/u4b/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 "bus/u4b/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
do_msc_reset(uint8_t lun)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
do_msc_cmd(uint8_t * pcmd,uint8_t cmdlen,void * pdata,uint32_t datalen,uint8_t isread,uint8_t isshort,uint8_t lun,uint8_t flags)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
do_msc_shorter_cmd(uint8_t lun)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
do_read_10(uint32_t lba,uint32_t len,void * buf,uint8_t lun)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
do_write_10(uint32_t lba,uint32_t len,void * buf,uint8_t lun)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
do_io_test(struct usb_msc_params * p,uint8_t lun,uint32_t lba_max,uint8_t * buffer,uint8_t * reference)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
usb_request_sense(uint8_t lun)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
usb_msc_test(struct usb_msc_params * p)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
show_host_device_selection(uint8_t level,uint16_t * pvid,uint16_t * ppid)860 show_host_device_selection(uint8_t level, uint16_t *pvid, uint16_t *ppid)
861 {
862           struct libusb20_backend *pbe;
863           struct libusb20_device *pdev;
864           struct LIBUSB20_DEVICE_DESC_DECODED *ddesc;
865 
866           uint16_t vid[USB_DEVICES_MAX];
867           uint16_t pid[USB_DEVICES_MAX];
868 
869           int index;
870           int sel;
871 
872           const char *ptr;
873 
874 top:
875           pbe = libusb20_be_alloc_default();
876           pdev = NULL;
877           index = 0;
878 
879           printf("\n[] Select USB device:\n");
880 
881           while ((pdev = libusb20_be_device_foreach(pbe, pdev))) {
882 
883                     if (libusb20_dev_get_mode(pdev) != LIBUSB20_MODE_HOST)
884                               continue;
885 
886                     if (index < USB_DEVICES_MAX) {
887                               ddesc = libusb20_dev_get_device_desc(pdev);
888                               ptr = libusb20_dev_get_desc(pdev);
889                               printf("%s%d) %s\n", indent[level], index, ptr);
890                               vid[index] = ddesc->idVendor;
891                               pid[index] = ddesc->idProduct;
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                     *pvid = 0;
911                     *ppid = 0;
912                     return;
913           }
914           *pvid = vid[sel];
915           *ppid = pid[sel];
916 }
917 
918 struct libusb20_device *
find_usb_device(uint16_t vid,uint16_t pid)919 find_usb_device(uint16_t vid, uint16_t pid)
920 {
921           struct libusb20_backend *pbe = libusb20_be_alloc_default();
922           struct libusb20_device *pdev = NULL;
923           struct LIBUSB20_DEVICE_DESC_DECODED *ddesc;
924 
925           while ((pdev = libusb20_be_device_foreach(pbe, pdev))) {
926 
927                     if (libusb20_dev_get_mode(pdev) != LIBUSB20_MODE_HOST)
928                               continue;
929 
930                     ddesc = libusb20_dev_get_device_desc(pdev);
931 
932                     if ((vid == ddesc->idVendor) &&
933                         (pid == ddesc->idProduct)) {
934                               libusb20_be_dequeue_device(pbe, pdev);
935                               break;
936                     }
937           }
938 
939           /* release data */
940           libusb20_be_free(pbe);
941 
942           return (pdev);
943 }
944 
945 void
find_usb_endpoints(struct libusb20_device * pdev,uint8_t class,uint8_t subclass,uint8_t protocol,uint8_t alt_setting,uint8_t * pif,uint8_t * in_ep,uint8_t * out_ep,uint8_t next_if)946 find_usb_endpoints(struct libusb20_device *pdev, uint8_t class,
947     uint8_t subclass, uint8_t protocol, uint8_t alt_setting,
948     uint8_t *pif, uint8_t *in_ep, uint8_t *out_ep, uint8_t next_if)
949 {
950           struct libusb20_config *pcfg;
951           struct libusb20_interface *iface;
952           struct libusb20_endpoint *ep;
953           uint8_t x;
954           uint8_t y;
955           uint8_t z;
956 
957           *in_ep = 0;
958           *out_ep = 0;
959           *pif = 0;
960 
961           pcfg = libusb20_dev_alloc_config(pdev,
962               libusb20_dev_get_config_index(pdev));
963 
964           if (pcfg == NULL)
965                     return;
966 
967           for (x = 0; x != pcfg->num_interface; x++) {
968 
969                     y = alt_setting;
970 
971                     iface = (pcfg->interface + x);
972 
973                     if ((iface->desc.bInterfaceClass == class) &&
974                         (iface->desc.bInterfaceSubClass == subclass ||
975                         subclass == 255) &&
976                         (iface->desc.bInterfaceProtocol == protocol ||
977                         protocol == 255)) {
978 
979                               if (next_if) {
980                                         x++;
981                                         if (x == pcfg->num_interface)
982                                                   break;
983                                         iface = (pcfg->interface + x);
984                               }
985                               *pif = x;
986 
987                               for (z = 0; z != iface->num_endpoints; z++) {
988                                         ep = iface->endpoints + z;
989 
990                                         /* BULK only */
991                                         if ((ep->desc.bmAttributes & 3) != 2)
992                                                   continue;
993 
994                                         if (ep->desc.bEndpointAddress & 0x80)
995                                                   *in_ep = ep->desc.bEndpointAddress;
996                                         else
997                                                   *out_ep = ep->desc.bEndpointAddress;
998                               }
999                               break;
1000                     }
1001           }
1002 
1003           free(pcfg);
1004 }
1005 
1006 static void
exec_host_msc_test(struct usb_msc_params * p,uint16_t vid,uint16_t pid)1007 exec_host_msc_test(struct usb_msc_params *p, uint16_t vid, uint16_t pid)
1008 {
1009           struct libusb20_device *pdev;
1010 
1011           uint8_t in_ep;
1012           uint8_t out_ep;
1013           uint8_t iface;
1014 
1015           int error;
1016 
1017           memset(&stats, 0, sizeof(stats));
1018 
1019           xfer_current_id = 0;
1020           xfer_wrapper_sig = CBWSIGNATURE;
1021 
1022           pdev = find_usb_device(vid, pid);
1023           if (pdev == NULL) {
1024                     printf("USB device not found\n");
1025                     return;
1026           }
1027           find_usb_endpoints(pdev, 8, 6, 0x50, 0, &iface, &in_ep, &out_ep, 0);
1028 
1029           if ((in_ep == 0) || (out_ep == 0)) {
1030                     printf("Could not find USB endpoints\n");
1031                     libusb20_dev_free(pdev);
1032                     return;
1033           }
1034           printf("Attaching to: %s @ iface %d\n",
1035               libusb20_dev_get_desc(pdev), iface);
1036 
1037           if (libusb20_dev_open(pdev, 2)) {
1038                     printf("Could not open USB device\n");
1039                     libusb20_dev_free(pdev);
1040                     return;
1041           }
1042           if (libusb20_dev_detach_kernel_driver(pdev, iface)) {
1043                     printf("WARNING: Could not detach kernel driver\n");
1044           }
1045           xfer_in = libusb20_tr_get_pointer(pdev, 0);
1046           error = libusb20_tr_open(xfer_in, 65536, 1, in_ep);
1047           if (error) {
1048                     printf("Could not open USB endpoint %d\n", in_ep);
1049                     libusb20_dev_free(pdev);
1050                     return;
1051           }
1052           xfer_out = libusb20_tr_get_pointer(pdev, 1);
1053           error = libusb20_tr_open(xfer_out, 65536, 1, out_ep);
1054           if (error) {
1055                     printf("Could not open USB endpoint %d\n", out_ep);
1056                     libusb20_dev_free(pdev);
1057                     return;
1058           }
1059           usb_pdev = pdev;
1060           usb_iface = iface;
1061 
1062           usb_msc_test(p);
1063 
1064           libusb20_dev_free(pdev);
1065 }
1066 
1067 static void
set_defaults(struct usb_msc_params * p)1068 set_defaults(struct usb_msc_params *p)
1069 {
1070           memset(p, 0, sizeof(*p));
1071 
1072           p->duration = 60;             /* seconds */
1073           p->try_invalid_scsi_command = 1;
1074           p->try_invalid_wrapper_block = 1;
1075           p->try_last_lba = 1;
1076           p->max_errors = -1;
1077 }
1078 
1079 static const char *
get_io_mode(const struct usb_msc_params * p)1080 get_io_mode(const struct usb_msc_params *p)
1081 {
1082           ;                                       /* indent fix */
1083           switch (p->io_mode) {
1084           case USB_MSC_IO_MODE_READ_ONLY:
1085                     return ("Read Only");
1086           case USB_MSC_IO_MODE_WRITE_ONCE_READ_ONLY:
1087                     return ("Write Once, Read Only");
1088           case USB_MSC_IO_MODE_WRITE_ONLY:
1089                     return ("Write Only");
1090           case USB_MSC_IO_MODE_READ_WRITE:
1091                     return ("Read and Write");
1092           default:
1093                     return ("Unknown");
1094           }
1095 }
1096 
1097 static const char *
get_io_pattern(const struct usb_msc_params * p)1098 get_io_pattern(const struct usb_msc_params *p)
1099 {
1100           ;                                       /* indent fix */
1101           switch (p->io_pattern) {
1102           case USB_MSC_IO_PATTERN_FIXED:
1103                     return ("Fixed");
1104           case USB_MSC_IO_PATTERN_RANDOM:
1105                     return ("Random");
1106           case USB_MSC_IO_PATTERN_PRESERVE:
1107                     return ("Preserve");
1108           default:
1109                     return ("Unknown");
1110           }
1111 }
1112 
1113 static const char *
get_io_size(const struct usb_msc_params * p)1114 get_io_size(const struct usb_msc_params *p)
1115 {
1116           ;                                       /* indent fix */
1117           switch (p->io_size) {
1118           case USB_MSC_IO_SIZE_RANDOM:
1119                     return ("Random");
1120           case USB_MSC_IO_SIZE_INCREASING:
1121                     return ("Increasing");
1122           case USB_MSC_IO_SIZE_FIXED_1BLK:
1123                     return ("Single block");
1124           case USB_MSC_IO_SIZE_FIXED_2BLK:
1125                     return ("2 blocks");
1126           case USB_MSC_IO_SIZE_FIXED_4BLK:
1127                     return ("4 blocks");
1128           case USB_MSC_IO_SIZE_FIXED_8BLK:
1129                     return ("8 blocks");
1130           case USB_MSC_IO_SIZE_FIXED_16BLK:
1131                     return ("16 blocks");
1132           case USB_MSC_IO_SIZE_FIXED_32BLK:
1133                     return ("32 blocks");
1134           case USB_MSC_IO_SIZE_FIXED_64BLK:
1135                     return ("64 blocks");
1136           case USB_MSC_IO_SIZE_FIXED_128BLK:
1137                     return ("128 blocks");
1138           case USB_MSC_IO_SIZE_FIXED_256BLK:
1139                     return ("256 blocks");
1140           case USB_MSC_IO_SIZE_FIXED_512BLK:
1141                     return ("512 blocks");
1142           case USB_MSC_IO_SIZE_FIXED_1024BLK:
1143                     return ("1024 blocks");
1144           default:
1145                     return ("Unknown");
1146           }
1147 }
1148 
1149 static const char *
get_io_delay(const struct usb_msc_params * p)1150 get_io_delay(const struct usb_msc_params *p)
1151 {
1152           ;                                       /* indent fix */
1153           switch (p->io_delay) {
1154           case USB_MSC_IO_DELAY_NONE:
1155                     return ("None");
1156           case USB_MSC_IO_DELAY_RANDOM_10MS:
1157                     return ("Random 10ms");
1158           case USB_MSC_IO_DELAY_RANDOM_100MS:
1159                     return ("Random 100ms");
1160           case USB_MSC_IO_DELAY_FIXED_10MS:
1161                     return ("Fixed 10ms");
1162           case USB_MSC_IO_DELAY_FIXED_100MS:
1163                     return ("Fixed 100ms");
1164           default:
1165                     return ("Unknown");
1166           }
1167 }
1168 
1169 static const char *
get_io_offset(const struct usb_msc_params * p)1170 get_io_offset(const struct usb_msc_params *p)
1171 {
1172           ;                                       /* indent fix */
1173           switch (p->io_offset) {
1174           case USB_MSC_IO_OFF_START_OF_DISK:
1175                     return ("Start Of Disk");
1176           case USB_MSC_IO_OFF_RANDOM:
1177                     return ("Random Offset");
1178           default:
1179                     return ("Unknown");
1180           }
1181 }
1182 
1183 static const char *
get_io_area(const struct usb_msc_params * p)1184 get_io_area(const struct usb_msc_params *p)
1185 {
1186           ;                                       /* indent fix */
1187           switch (p->io_area) {
1188           case USB_MSC_IO_AREA_COMPLETE:
1189                     return ("Complete Disk");
1190           case USB_MSC_IO_AREA_1MB:
1191                     return ("First MegaByte");
1192           case USB_MSC_IO_AREA_16MB:
1193                     return ("First 16 MegaBytes");
1194           case USB_MSC_IO_AREA_256MB:
1195                     return ("First 256 MegaBytes");
1196           default:
1197                     return ("Unknown");
1198           }
1199 }
1200 
1201 void
show_host_msc_test(uint8_t level,uint16_t vid,uint16_t pid,uint32_t duration)1202 show_host_msc_test(uint8_t level, uint16_t vid,
1203     uint16_t pid, 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                         vid, 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, vid, pid);
1321                               break;
1322                     case 40:
1323                               show_host_device_selection(level + 1, &vid, &pid);
1324                               break;
1325                     default:
1326                               return;
1327                     }
1328           }
1329 }
1330