]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - sys/dev/usb/usb_msctest.c
MFC r361581:
[FreeBSD/stable/9.git] / sys / dev / usb / usb_msctest.c
1 /* $FreeBSD$ */
2 /*-
3  * Copyright (c) 2008,2011 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 /*
28  * The following file contains code that will detect USB autoinstall
29  * disks.
30  *
31  * TODO: Potentially we could add code to automatically detect USB
32  * mass storage quirks for not supported SCSI commands!
33  */
34
35 #include <sys/stdint.h>
36 #include <sys/stddef.h>
37 #include <sys/param.h>
38 #include <sys/queue.h>
39 #include <sys/types.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/bus.h>
43 #include <sys/module.h>
44 #include <sys/lock.h>
45 #include <sys/mutex.h>
46 #include <sys/condvar.h>
47 #include <sys/sysctl.h>
48 #include <sys/sx.h>
49 #include <sys/unistd.h>
50 #include <sys/callout.h>
51 #include <sys/malloc.h>
52 #include <sys/priv.h>
53
54 #include <dev/usb/usb.h>
55 #include <dev/usb/usbdi.h>
56 #include <dev/usb/usbdi_util.h>
57
58 #define USB_DEBUG_VAR usb_debug
59
60 #include <dev/usb/usb_busdma.h>
61 #include <dev/usb/usb_process.h>
62 #include <dev/usb/usb_transfer.h>
63 #include <dev/usb/usb_msctest.h>
64 #include <dev/usb/usb_debug.h>
65 #include <dev/usb/usb_device.h>
66 #include <dev/usb/usb_request.h>
67 #include <dev/usb/usb_util.h>
68 #include <dev/usb/quirk/usb_quirk.h>
69
70 enum {
71         ST_COMMAND,
72         ST_DATA_RD,
73         ST_DATA_RD_CS,
74         ST_DATA_WR,
75         ST_DATA_WR_CS,
76         ST_STATUS,
77         ST_MAX,
78 };
79
80 enum {
81         DIR_IN,
82         DIR_OUT,
83         DIR_NONE,
84 };
85
86 #define SCSI_MAX_LEN    MAX(0x100, BULK_SIZE)
87 #define SCSI_INQ_LEN    0x24
88 #define SCSI_SENSE_LEN  0xFF
89
90 static uint8_t scsi_test_unit_ready[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
91 static uint8_t scsi_inquiry[] = { 0x12, 0x00, 0x00, 0x00, SCSI_INQ_LEN, 0x00 };
92 static uint8_t scsi_rezero_init[] =     { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 };
93 static uint8_t scsi_start_stop_unit[] = { 0x1b, 0x00, 0x00, 0x00, 0x02, 0x00 };
94 static uint8_t scsi_ztestor_eject[] =   { 0x85, 0x01, 0x01, 0x01, 0x18, 0x01,
95                                           0x01, 0x01, 0x01, 0x01, 0x00, 0x00 };
96 static uint8_t scsi_cmotech_eject[] =   { 0xff, 0x52, 0x44, 0x45, 0x56, 0x43,
97                                           0x48, 0x47 };
98 static uint8_t scsi_huawei_eject[] =    { 0x11, 0x06, 0x00, 0x00, 0x00, 0x00,
99                                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100                                           0x00, 0x00, 0x00, 0x00 };
101 static uint8_t scsi_huawei_eject2[] =   { 0x11, 0x06, 0x20, 0x00, 0x00, 0x01,
102                                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103                                           0x00, 0x00, 0x00, 0x00 };
104 static uint8_t scsi_tct_eject[] =       { 0x06, 0xf5, 0x04, 0x02, 0x52, 0x70 };
105 static uint8_t scsi_sync_cache[] =      { 0x35, 0x00, 0x00, 0x00, 0x00, 0x00,
106                                           0x00, 0x00, 0x00, 0x00 };
107 static uint8_t scsi_request_sense[] =   { 0x03, 0x00, 0x00, 0x00, 0x12, 0x00,
108                                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
109 static uint8_t scsi_read_capacity[] =   { 0x25, 0x00, 0x00, 0x00, 0x00, 0x00,
110                                           0x00, 0x00, 0x00, 0x00 };
111 static uint8_t scsi_prevent_removal[] = { 0x1e, 0, 0, 0, 1, 0 };
112 static uint8_t scsi_allow_removal[] =   { 0x1e, 0, 0, 0, 0, 0 };
113
114 #define BULK_SIZE               64      /* dummy */
115 #define ERR_CSW_FAILED          -1
116
117 /* Command Block Wrapper */
118 struct bbb_cbw {
119         uDWord  dCBWSignature;
120 #define CBWSIGNATURE    0x43425355
121         uDWord  dCBWTag;
122         uDWord  dCBWDataTransferLength;
123         uByte   bCBWFlags;
124 #define CBWFLAGS_OUT    0x00
125 #define CBWFLAGS_IN     0x80
126         uByte   bCBWLUN;
127         uByte   bCDBLength;
128 #define CBWCDBLENGTH    16
129         uByte   CBWCDB[CBWCDBLENGTH];
130 } __packed;
131
132 /* Command Status Wrapper */
133 struct bbb_csw {
134         uDWord  dCSWSignature;
135 #define CSWSIGNATURE    0x53425355
136         uDWord  dCSWTag;
137         uDWord  dCSWDataResidue;
138         uByte   bCSWStatus;
139 #define CSWSTATUS_GOOD  0x0
140 #define CSWSTATUS_FAILED        0x1
141 #define CSWSTATUS_PHASE 0x2
142 } __packed;
143
144 struct bbb_transfer {
145         struct mtx mtx;
146         struct cv cv;
147         struct bbb_cbw *cbw;
148         struct bbb_csw *csw;
149
150         struct usb_xfer *xfer[ST_MAX];
151
152         uint8_t *data_ptr;
153
154         usb_size_t data_len;            /* bytes */
155         usb_size_t data_rem;            /* bytes */
156         usb_timeout_t data_timeout;     /* ms */
157         usb_frlength_t actlen;          /* bytes */
158         usb_frlength_t buffer_size;     /* bytes */
159
160         uint8_t cmd_len;                /* bytes */
161         uint8_t dir;
162         uint8_t lun;
163         uint8_t state;
164         uint8_t status_try;
165         int     error;
166
167         uint8_t *buffer;
168 };
169
170 static usb_callback_t bbb_command_callback;
171 static usb_callback_t bbb_data_read_callback;
172 static usb_callback_t bbb_data_rd_cs_callback;
173 static usb_callback_t bbb_data_write_callback;
174 static usb_callback_t bbb_data_wr_cs_callback;
175 static usb_callback_t bbb_status_callback;
176 static usb_callback_t bbb_raw_write_callback;
177
178 static void     bbb_done(struct bbb_transfer *, int);
179 static void     bbb_transfer_start(struct bbb_transfer *, uint8_t);
180 static void     bbb_data_clear_stall_callback(struct usb_xfer *, uint8_t,
181                     uint8_t);
182 static int      bbb_command_start(struct bbb_transfer *, uint8_t, uint8_t,
183                     void *, size_t, void *, size_t, usb_timeout_t);
184 static struct bbb_transfer *bbb_attach(struct usb_device *, uint8_t, uint8_t);
185 static void     bbb_detach(struct bbb_transfer *);
186
187 static const struct usb_config bbb_config[ST_MAX] = {
188
189         [ST_COMMAND] = {
190                 .type = UE_BULK,
191                 .endpoint = UE_ADDR_ANY,
192                 .direction = UE_DIR_OUT,
193                 .bufsize = sizeof(struct bbb_cbw),
194                 .callback = &bbb_command_callback,
195                 .timeout = 4 * USB_MS_HZ,       /* 4 seconds */
196         },
197
198         [ST_DATA_RD] = {
199                 .type = UE_BULK,
200                 .endpoint = UE_ADDR_ANY,
201                 .direction = UE_DIR_IN,
202                 .bufsize = SCSI_MAX_LEN,
203                 .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,},
204                 .callback = &bbb_data_read_callback,
205                 .timeout = 4 * USB_MS_HZ,       /* 4 seconds */
206         },
207
208         [ST_DATA_RD_CS] = {
209                 .type = UE_CONTROL,
210                 .endpoint = 0x00,       /* Control pipe */
211                 .direction = UE_DIR_ANY,
212                 .bufsize = sizeof(struct usb_device_request),
213                 .callback = &bbb_data_rd_cs_callback,
214                 .timeout = 1 * USB_MS_HZ,       /* 1 second  */
215         },
216
217         [ST_DATA_WR] = {
218                 .type = UE_BULK,
219                 .endpoint = UE_ADDR_ANY,
220                 .direction = UE_DIR_OUT,
221                 .bufsize = SCSI_MAX_LEN,
222                 .flags = {.ext_buffer = 1,.proxy_buffer = 1,},
223                 .callback = &bbb_data_write_callback,
224                 .timeout = 4 * USB_MS_HZ,       /* 4 seconds */
225         },
226
227         [ST_DATA_WR_CS] = {
228                 .type = UE_CONTROL,
229                 .endpoint = 0x00,       /* Control pipe */
230                 .direction = UE_DIR_ANY,
231                 .bufsize = sizeof(struct usb_device_request),
232                 .callback = &bbb_data_wr_cs_callback,
233                 .timeout = 1 * USB_MS_HZ,       /* 1 second  */
234         },
235
236         [ST_STATUS] = {
237                 .type = UE_BULK,
238                 .endpoint = UE_ADDR_ANY,
239                 .direction = UE_DIR_IN,
240                 .bufsize = sizeof(struct bbb_csw),
241                 .flags = {.short_xfer_ok = 1,},
242                 .callback = &bbb_status_callback,
243                 .timeout = 1 * USB_MS_HZ,       /* 1 second  */
244         },
245 };
246
247 static const struct usb_config bbb_raw_config[1] = {
248
249         [0] = {
250                 .type = UE_BULK_INTR,
251                 .endpoint = UE_ADDR_ANY,
252                 .direction = UE_DIR_OUT,
253                 .bufsize = SCSI_MAX_LEN,
254                 .flags = {.ext_buffer = 1,.proxy_buffer = 1,},
255                 .callback = &bbb_raw_write_callback,
256                 .timeout = 1 * USB_MS_HZ,       /* 1 second */
257         },
258 };
259
260 static void
261 bbb_done(struct bbb_transfer *sc, int error)
262 {
263         sc->error = error;
264         sc->state = ST_COMMAND;
265         sc->status_try = 1;
266         cv_signal(&sc->cv);
267 }
268
269 static void
270 bbb_transfer_start(struct bbb_transfer *sc, uint8_t xfer_index)
271 {
272         sc->state = xfer_index;
273         usbd_transfer_start(sc->xfer[xfer_index]);
274 }
275
276 static void
277 bbb_data_clear_stall_callback(struct usb_xfer *xfer,
278     uint8_t next_xfer, uint8_t stall_xfer)
279 {
280         struct bbb_transfer *sc = usbd_xfer_softc(xfer);
281
282         if (usbd_clear_stall_callback(xfer, sc->xfer[stall_xfer])) {
283                 switch (USB_GET_STATE(xfer)) {
284                 case USB_ST_SETUP:
285                 case USB_ST_TRANSFERRED:
286                         bbb_transfer_start(sc, next_xfer);
287                         break;
288                 default:
289                         bbb_done(sc, USB_ERR_STALLED);
290                         break;
291                 }
292         }
293 }
294
295 static void
296 bbb_command_callback(struct usb_xfer *xfer, usb_error_t error)
297 {
298         struct bbb_transfer *sc = usbd_xfer_softc(xfer);
299         uint32_t tag;
300
301         switch (USB_GET_STATE(xfer)) {
302         case USB_ST_TRANSFERRED:
303                 bbb_transfer_start
304                     (sc, ((sc->dir == DIR_IN) ? ST_DATA_RD :
305                     (sc->dir == DIR_OUT) ? ST_DATA_WR :
306                     ST_STATUS));
307                 break;
308
309         case USB_ST_SETUP:
310                 sc->status_try = 0;
311                 tag = UGETDW(sc->cbw->dCBWTag) + 1;
312                 USETDW(sc->cbw->dCBWSignature, CBWSIGNATURE);
313                 USETDW(sc->cbw->dCBWTag, tag);
314                 USETDW(sc->cbw->dCBWDataTransferLength, (uint32_t)sc->data_len);
315                 sc->cbw->bCBWFlags = ((sc->dir == DIR_IN) ? CBWFLAGS_IN : CBWFLAGS_OUT);
316                 sc->cbw->bCBWLUN = sc->lun;
317                 sc->cbw->bCDBLength = sc->cmd_len;
318                 if (sc->cbw->bCDBLength > sizeof(sc->cbw->CBWCDB)) {
319                         sc->cbw->bCDBLength = sizeof(sc->cbw->CBWCDB);
320                         DPRINTFN(0, "Truncating long command\n");
321                 }
322                 usbd_xfer_set_frame_len(xfer, 0,
323                     sizeof(struct bbb_cbw));
324                 usbd_transfer_submit(xfer);
325                 break;
326
327         default:                        /* Error */
328                 bbb_done(sc, error);
329                 break;
330         }
331 }
332
333 static void
334 bbb_data_read_callback(struct usb_xfer *xfer, usb_error_t error)
335 {
336         struct bbb_transfer *sc = usbd_xfer_softc(xfer);
337         usb_frlength_t max_bulk = usbd_xfer_max_len(xfer);
338         int actlen, sumlen;
339
340         usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
341
342         switch (USB_GET_STATE(xfer)) {
343         case USB_ST_TRANSFERRED:
344                 sc->data_rem -= actlen;
345                 sc->data_ptr += actlen;
346                 sc->actlen += actlen;
347
348                 if (actlen < sumlen) {
349                         /* short transfer */
350                         sc->data_rem = 0;
351                 }
352         case USB_ST_SETUP:
353                 DPRINTF("max_bulk=%d, data_rem=%d\n",
354                     max_bulk, sc->data_rem);
355
356                 if (sc->data_rem == 0) {
357                         bbb_transfer_start(sc, ST_STATUS);
358                         break;
359                 }
360                 if (max_bulk > sc->data_rem) {
361                         max_bulk = sc->data_rem;
362                 }
363                 usbd_xfer_set_timeout(xfer, sc->data_timeout);
364                 usbd_xfer_set_frame_data(xfer, 0, sc->data_ptr, max_bulk);
365                 usbd_transfer_submit(xfer);
366                 break;
367
368         default:                        /* Error */
369                 if (error == USB_ERR_CANCELLED) {
370                         bbb_done(sc, error);
371                 } else {
372                         bbb_transfer_start(sc, ST_DATA_RD_CS);
373                 }
374                 break;
375         }
376 }
377
378 static void
379 bbb_data_rd_cs_callback(struct usb_xfer *xfer, usb_error_t error)
380 {
381         bbb_data_clear_stall_callback(xfer, ST_STATUS,
382             ST_DATA_RD);
383 }
384
385 static void
386 bbb_data_write_callback(struct usb_xfer *xfer, usb_error_t error)
387 {
388         struct bbb_transfer *sc = usbd_xfer_softc(xfer);
389         usb_frlength_t max_bulk = usbd_xfer_max_len(xfer);
390         int actlen, sumlen;
391
392         usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
393
394         switch (USB_GET_STATE(xfer)) {
395         case USB_ST_TRANSFERRED:
396                 sc->data_rem -= actlen;
397                 sc->data_ptr += actlen;
398                 sc->actlen += actlen;
399
400                 if (actlen < sumlen) {
401                         /* short transfer */
402                         sc->data_rem = 0;
403                 }
404         case USB_ST_SETUP:
405                 DPRINTF("max_bulk=%d, data_rem=%d\n",
406                     max_bulk, sc->data_rem);
407
408                 if (sc->data_rem == 0) {
409                         bbb_transfer_start(sc, ST_STATUS);
410                         break;
411                 }
412                 if (max_bulk > sc->data_rem) {
413                         max_bulk = sc->data_rem;
414                 }
415                 usbd_xfer_set_timeout(xfer, sc->data_timeout);
416                 usbd_xfer_set_frame_data(xfer, 0, sc->data_ptr, max_bulk);
417                 usbd_transfer_submit(xfer);
418                 break;
419
420         default:                        /* Error */
421                 if (error == USB_ERR_CANCELLED) {
422                         bbb_done(sc, error);
423                 } else {
424                         bbb_transfer_start(sc, ST_DATA_WR_CS);
425                 }
426                 break;
427         }
428 }
429
430 static void
431 bbb_data_wr_cs_callback(struct usb_xfer *xfer, usb_error_t error)
432 {
433         bbb_data_clear_stall_callback(xfer, ST_STATUS,
434             ST_DATA_WR);
435 }
436
437 static void
438 bbb_status_callback(struct usb_xfer *xfer, usb_error_t error)
439 {
440         struct bbb_transfer *sc = usbd_xfer_softc(xfer);
441         int actlen;
442         int sumlen;
443
444         usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
445
446         switch (USB_GET_STATE(xfer)) {
447         case USB_ST_TRANSFERRED:
448
449                 /* very simple status check */
450
451                 if (actlen < (int)sizeof(struct bbb_csw)) {
452                         bbb_done(sc, USB_ERR_SHORT_XFER);
453                 } else if (sc->csw->bCSWStatus == CSWSTATUS_GOOD) {
454                         bbb_done(sc, 0);        /* success */
455                 } else {
456                         bbb_done(sc, ERR_CSW_FAILED);   /* error */
457                 }
458                 break;
459
460         case USB_ST_SETUP:
461                 usbd_xfer_set_frame_len(xfer, 0,
462                     sizeof(struct bbb_csw));
463                 usbd_transfer_submit(xfer);
464                 break;
465
466         default:
467                 DPRINTF("Failed to read CSW: %s, try %d\n",
468                     usbd_errstr(error), sc->status_try);
469
470                 if (error == USB_ERR_CANCELLED || sc->status_try) {
471                         bbb_done(sc, error);
472                 } else {
473                         sc->status_try = 1;
474                         bbb_transfer_start(sc, ST_DATA_RD_CS);
475                 }
476                 break;
477         }
478 }
479
480 static void
481 bbb_raw_write_callback(struct usb_xfer *xfer, usb_error_t error)
482 {
483         struct bbb_transfer *sc = usbd_xfer_softc(xfer);
484         usb_frlength_t max_bulk = usbd_xfer_max_len(xfer);
485         int actlen, sumlen;
486
487         usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
488
489         switch (USB_GET_STATE(xfer)) {
490         case USB_ST_TRANSFERRED:
491                 sc->data_rem -= actlen;
492                 sc->data_ptr += actlen;
493                 sc->actlen += actlen;
494
495                 if (actlen < sumlen) {
496                         /* short transfer */
497                         sc->data_rem = 0;
498                 }
499         case USB_ST_SETUP:
500                 DPRINTF("max_bulk=%d, data_rem=%d\n",
501                     max_bulk, sc->data_rem);
502
503                 if (sc->data_rem == 0) {
504                         bbb_done(sc, 0);
505                         break;
506                 }
507                 if (max_bulk > sc->data_rem) {
508                         max_bulk = sc->data_rem;
509                 }
510                 usbd_xfer_set_timeout(xfer, sc->data_timeout);
511                 usbd_xfer_set_frame_data(xfer, 0, sc->data_ptr, max_bulk);
512                 usbd_transfer_submit(xfer);
513                 break;
514
515         default:                        /* Error */
516                 bbb_done(sc, error);
517                 break;
518         }
519 }
520
521 /*------------------------------------------------------------------------*
522  *      bbb_command_start - execute a SCSI command synchronously
523  *
524  * Return values
525  * 0: Success
526  * Else: Failure
527  *------------------------------------------------------------------------*/
528 static int
529 bbb_command_start(struct bbb_transfer *sc, uint8_t dir, uint8_t lun,
530     void *data_ptr, size_t data_len, void *cmd_ptr, size_t cmd_len,
531     usb_timeout_t data_timeout)
532 {
533         sc->lun = lun;
534         sc->dir = data_len ? dir : DIR_NONE;
535         sc->data_ptr = data_ptr;
536         sc->data_len = data_len;
537         sc->data_rem = data_len;
538         sc->data_timeout = (data_timeout + USB_MS_HZ);
539         sc->actlen = 0;
540         sc->error = 0;
541         sc->cmd_len = cmd_len;
542         memset(&sc->cbw->CBWCDB, 0, sizeof(sc->cbw->CBWCDB));
543         memcpy(&sc->cbw->CBWCDB, cmd_ptr, cmd_len);
544         DPRINTFN(1, "SCSI cmd = %*D\n", (int)cmd_len, (char *)sc->cbw->CBWCDB, ":");
545
546         mtx_lock(&sc->mtx);
547         usbd_transfer_start(sc->xfer[sc->state]);
548
549         while (usbd_transfer_pending(sc->xfer[sc->state])) {
550                 cv_wait(&sc->cv, &sc->mtx);
551         }
552         mtx_unlock(&sc->mtx);
553         return (sc->error);
554 }
555
556 /*------------------------------------------------------------------------*
557  *      bbb_raw_write - write a raw BULK message synchronously
558  *
559  * Return values
560  * 0: Success
561  * Else: Failure
562  *------------------------------------------------------------------------*/
563 static int
564 bbb_raw_write(struct bbb_transfer *sc, const void *data_ptr, size_t data_len,
565     usb_timeout_t data_timeout)
566 {
567         sc->data_ptr = __DECONST(void *, data_ptr);
568         sc->data_len = data_len;
569         sc->data_rem = data_len;
570         sc->data_timeout = (data_timeout + USB_MS_HZ);
571         sc->actlen = 0;
572         sc->error = 0;
573
574         DPRINTFN(1, "BULK DATA = %*D\n", (int)data_len,
575             (const char *)data_ptr, ":");
576
577         mtx_lock(&sc->mtx);
578         usbd_transfer_start(sc->xfer[0]);
579         while (usbd_transfer_pending(sc->xfer[0]))
580                 cv_wait(&sc->cv, &sc->mtx);
581         mtx_unlock(&sc->mtx);
582         return (sc->error);
583 }
584
585 static struct bbb_transfer *
586 bbb_attach(struct usb_device *udev, uint8_t iface_index,
587     uint8_t bInterfaceClass)
588 {
589         struct usb_interface *iface;
590         struct usb_interface_descriptor *id;
591         const struct usb_config *pconfig;
592         struct bbb_transfer *sc;
593         usb_error_t err;
594         int nconfig;
595         uint8_t do_unlock;
596
597         /* Prevent re-enumeration */
598         do_unlock = usbd_enum_lock(udev);
599
600         /*
601          * Make sure any driver which is hooked up to this interface,
602          * like umass is gone:
603          */
604         usb_detach_device(udev, iface_index, 0);
605
606         if (do_unlock)
607                 usbd_enum_unlock(udev);
608
609         iface = usbd_get_iface(udev, iface_index);
610         if (iface == NULL)
611                 return (NULL);
612
613         id = iface->idesc;
614         if (id == NULL || id->bInterfaceClass != bInterfaceClass)
615                 return (NULL);
616
617         switch (id->bInterfaceClass) {
618         case UICLASS_MASS:
619                 switch (id->bInterfaceSubClass) {
620                 case UISUBCLASS_SCSI:
621                 case UISUBCLASS_UFI:
622                 case UISUBCLASS_SFF8020I:
623                 case UISUBCLASS_SFF8070I:
624                         break;
625                 default:
626                         return (NULL);
627                 }
628                 switch (id->bInterfaceProtocol) {
629                 case UIPROTO_MASS_BBB_OLD:
630                 case UIPROTO_MASS_BBB:
631                         break;
632                 default:
633                         return (NULL);
634                 }
635                 pconfig = bbb_config;
636                 nconfig = ST_MAX;
637                 break;
638         case UICLASS_HID:
639                 switch (id->bInterfaceSubClass) {
640                 case 0:
641                         break;
642                 default:
643                         return (NULL);
644                 }
645                 pconfig = bbb_raw_config;
646                 nconfig = 1;
647                 break;
648         default:
649                 return (NULL);
650         }
651
652         sc = malloc(sizeof(*sc), M_USB, M_WAITOK | M_ZERO);
653         mtx_init(&sc->mtx, "USB autoinstall", NULL, MTX_DEF);
654         cv_init(&sc->cv, "WBBB");
655
656         err = usbd_transfer_setup(udev, &iface_index, sc->xfer, pconfig,
657             nconfig, sc, &sc->mtx);
658         if (err) {
659                 bbb_detach(sc);
660                 return (NULL);
661         }
662         switch (id->bInterfaceClass) {
663         case UICLASS_MASS:
664                 /* store pointer to DMA buffers */
665                 sc->buffer = usbd_xfer_get_frame_buffer(
666                     sc->xfer[ST_DATA_RD], 0);
667                 sc->buffer_size =
668                     usbd_xfer_max_len(sc->xfer[ST_DATA_RD]);
669                 sc->cbw = usbd_xfer_get_frame_buffer(
670                     sc->xfer[ST_COMMAND], 0);
671                 sc->csw = usbd_xfer_get_frame_buffer(
672                     sc->xfer[ST_STATUS], 0);
673                 break;
674         default:
675                 break;
676         }
677         return (sc);
678 }
679
680 static void
681 bbb_detach(struct bbb_transfer *sc)
682 {
683         usbd_transfer_unsetup(sc->xfer, ST_MAX);
684         mtx_destroy(&sc->mtx);
685         cv_destroy(&sc->cv);
686         free(sc, M_USB);
687 }
688
689 /*------------------------------------------------------------------------*
690  *      usb_iface_is_cdrom
691  *
692  * Return values:
693  * 1: This interface is an auto install disk (CD-ROM)
694  * 0: Not an auto install disk.
695  *------------------------------------------------------------------------*/
696 int
697 usb_iface_is_cdrom(struct usb_device *udev, uint8_t iface_index)
698 {
699         struct bbb_transfer *sc;
700         uint8_t timeout;
701         uint8_t is_cdrom;
702         uint8_t sid_type;
703         int err;
704
705         sc = bbb_attach(udev, iface_index, UICLASS_MASS);
706         if (sc == NULL)
707                 return (0);
708
709         is_cdrom = 0;
710         timeout = 4;    /* tries */
711         while (--timeout) {
712                 err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
713                     SCSI_INQ_LEN, &scsi_inquiry, sizeof(scsi_inquiry),
714                     USB_MS_HZ);
715
716                 if (err == 0 && sc->actlen > 0) {
717                         sid_type = sc->buffer[0] & 0x1F;
718                         if (sid_type == 0x05)
719                                 is_cdrom = 1;
720                         break;
721                 } else if (err != ERR_CSW_FAILED)
722                         break;  /* non retryable error */
723                 usb_pause_mtx(NULL, hz);
724         }
725         bbb_detach(sc);
726         return (is_cdrom);
727 }
728
729 static uint8_t
730 usb_msc_get_max_lun(struct usb_device *udev, uint8_t iface_index)
731 {
732         struct usb_device_request req;
733         usb_error_t err;
734         uint8_t buf = 0;
735
736
737         /* The Get Max Lun command is a class-specific request. */
738         req.bmRequestType = UT_READ_CLASS_INTERFACE;
739         req.bRequest = 0xFE;            /* GET_MAX_LUN */
740         USETW(req.wValue, 0);
741         req.wIndex[0] = iface_index;
742         req.wIndex[1] = 0;
743         USETW(req.wLength, 1);
744
745         err = usbd_do_request(udev, NULL, &req, &buf);
746         if (err)
747                 buf = 0;
748
749         return (buf);
750 }
751
752 usb_error_t
753 usb_msc_auto_quirk(struct usb_device *udev, uint8_t iface_index)
754 {
755         struct bbb_transfer *sc;
756         uint8_t timeout;
757         uint8_t is_no_direct;
758         uint8_t sid_type;
759         int err;
760
761         sc = bbb_attach(udev, iface_index, UICLASS_MASS);
762         if (sc == NULL)
763                 return (0);
764
765         /*
766          * Some devices need a delay after that the configuration
767          * value is set to function properly:
768          */
769         usb_pause_mtx(NULL, hz);
770
771         if (usb_msc_get_max_lun(udev, iface_index) == 0) {
772                 DPRINTF("Device has only got one LUN.\n");
773                 usbd_add_dynamic_quirk(udev, UQ_MSC_NO_GETMAXLUN);
774         }
775
776         is_no_direct = 1;
777         for (timeout = 4; timeout != 0; timeout--) {
778                 err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
779                     SCSI_INQ_LEN, &scsi_inquiry, sizeof(scsi_inquiry),
780                     USB_MS_HZ);
781
782                 if (err == 0 && sc->actlen > 0) {
783                         sid_type = sc->buffer[0] & 0x1F;
784                         if (sid_type == 0x00)
785                                 is_no_direct = 0;
786                         break;
787                 } else if (err != ERR_CSW_FAILED) {
788                         DPRINTF("Device is not responding "
789                             "properly to SCSI INQUIRY command.\n");
790                         goto error;     /* non retryable error */
791                 }
792                 usb_pause_mtx(NULL, hz);
793         }
794
795         if (is_no_direct) {
796                 DPRINTF("Device is not direct access.\n");
797                 goto done;
798         }
799
800         err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
801             &scsi_test_unit_ready, sizeof(scsi_test_unit_ready),
802             USB_MS_HZ);
803
804         if (err != 0) {
805                 if (err != ERR_CSW_FAILED)
806                         goto error;
807                 DPRINTF("Test unit ready failed\n");
808         }
809
810         err = bbb_command_start(sc, DIR_OUT, 0, NULL, 0,
811             &scsi_prevent_removal, sizeof(scsi_prevent_removal),
812             USB_MS_HZ);
813
814         if (err == 0) {
815                 err = bbb_command_start(sc, DIR_OUT, 0, NULL, 0,
816                     &scsi_allow_removal, sizeof(scsi_allow_removal),
817                     USB_MS_HZ);
818         }
819
820         if (err != 0) {
821                 if (err != ERR_CSW_FAILED)
822                         goto error;
823                 DPRINTF("Device doesn't handle prevent and allow removal\n");
824                 usbd_add_dynamic_quirk(udev, UQ_MSC_NO_PREVENT_ALLOW);
825         }
826
827         timeout = 1;
828
829 retry_sync_cache:
830         err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
831             &scsi_sync_cache, sizeof(scsi_sync_cache),
832             USB_MS_HZ);
833
834         if (err != 0) {
835
836                 if (err != ERR_CSW_FAILED)
837                         goto error;
838
839                 DPRINTF("Device doesn't handle synchronize cache\n");
840
841                 usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE);
842         } else {
843
844                 /*
845                  * Certain Kingston memory sticks fail the first
846                  * read capacity after a synchronize cache command
847                  * has been issued. Disable the synchronize cache
848                  * command for such devices.
849                  */
850
851                 err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 8,
852                     &scsi_read_capacity, sizeof(scsi_read_capacity),
853                     USB_MS_HZ);
854
855                 if (err != 0) {
856                         if (err != ERR_CSW_FAILED)
857                                 goto error;
858
859                         err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 8,
860                             &scsi_read_capacity, sizeof(scsi_read_capacity),
861                             USB_MS_HZ);
862
863                         if (err == 0) {
864                                 if (timeout--)
865                                         goto retry_sync_cache;
866
867                                 DPRINTF("Device most likely doesn't "
868                                     "handle synchronize cache\n");
869
870                                 usbd_add_dynamic_quirk(udev,
871                                     UQ_MSC_NO_SYNC_CACHE);
872                         } else {
873                                 if (err != ERR_CSW_FAILED)
874                                         goto error;
875                         }
876                 }
877         }
878
879         /* clear sense status of any failed commands on the device */
880
881         err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
882             SCSI_INQ_LEN, &scsi_inquiry, sizeof(scsi_inquiry),
883             USB_MS_HZ);
884
885         DPRINTF("Inquiry = %d\n", err);
886
887         if (err != 0) {
888
889                 if (err != ERR_CSW_FAILED)
890                         goto error;
891         }
892
893         err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
894             SCSI_SENSE_LEN, &scsi_request_sense,
895             sizeof(scsi_request_sense), USB_MS_HZ);
896
897         DPRINTF("Request sense = %d\n", err);
898
899         if (err != 0) {
900
901                 if (err != ERR_CSW_FAILED)
902                         goto error;
903         }
904
905 done:
906         bbb_detach(sc);
907         return (0);
908
909 error:
910         bbb_detach(sc);
911
912         DPRINTF("Device did not respond, enabling all quirks\n");
913
914         usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE);
915         usbd_add_dynamic_quirk(udev, UQ_MSC_NO_PREVENT_ALLOW);
916         usbd_add_dynamic_quirk(udev, UQ_MSC_NO_TEST_UNIT_READY);
917
918         /* Need to re-enumerate the device */
919         usbd_req_re_enumerate(udev, NULL);
920
921         return (USB_ERR_STALLED);
922 }
923
924 usb_error_t
925 usb_msc_eject(struct usb_device *udev, uint8_t iface_index, int method)
926 {
927         struct bbb_transfer *sc;
928         usb_error_t err;
929
930         sc = bbb_attach(udev, iface_index, UICLASS_MASS);
931         if (sc == NULL)
932                 return (USB_ERR_INVAL);
933
934         switch (method) {
935         case MSC_EJECT_STOPUNIT:
936                 err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
937                     &scsi_test_unit_ready, sizeof(scsi_test_unit_ready),
938                     USB_MS_HZ);
939                 DPRINTF("Test unit ready status: %s\n", usbd_errstr(err));
940                 err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
941                     &scsi_start_stop_unit, sizeof(scsi_start_stop_unit),
942                     USB_MS_HZ);
943                 break;
944         case MSC_EJECT_REZERO:
945                 err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
946                     &scsi_rezero_init, sizeof(scsi_rezero_init),
947                     USB_MS_HZ);
948                 break;
949         case MSC_EJECT_ZTESTOR:
950                 err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
951                     &scsi_ztestor_eject, sizeof(scsi_ztestor_eject),
952                     USB_MS_HZ);
953                 break;
954         case MSC_EJECT_CMOTECH:
955                 err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
956                     &scsi_cmotech_eject, sizeof(scsi_cmotech_eject),
957                     USB_MS_HZ);
958                 break;
959         case MSC_EJECT_HUAWEI:
960                 err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
961                     &scsi_huawei_eject, sizeof(scsi_huawei_eject),
962                     USB_MS_HZ);
963                 break;
964         case MSC_EJECT_HUAWEI2:
965                 err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
966                     &scsi_huawei_eject2, sizeof(scsi_huawei_eject2),
967                     USB_MS_HZ);
968                 break;
969         case MSC_EJECT_TCT:
970                 /*
971                  * TCTMobile needs DIR_IN flag. To get it, we
972                  * supply a dummy data with the command.
973                  */
974                 err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
975                     sc->buffer_size, &scsi_tct_eject,
976                     sizeof(scsi_tct_eject), USB_MS_HZ);
977                 break;
978         default:
979                 DPRINTF("Unknown eject method (%d)\n", method);
980                 bbb_detach(sc);
981                 return (USB_ERR_INVAL);
982         }
983
984         DPRINTF("Eject CD command status: %s\n", usbd_errstr(err));
985
986         bbb_detach(sc);
987         return (0);
988 }
989
990 usb_error_t
991 usb_dymo_eject(struct usb_device *udev, uint8_t iface_index)
992 {
993         static const uint8_t data[3] = { 0x1b, 0x5a, 0x01 };
994         struct bbb_transfer *sc;
995         usb_error_t err;
996
997         sc = bbb_attach(udev, iface_index, UICLASS_HID);
998         if (sc == NULL)
999                 return (USB_ERR_INVAL);
1000         err = bbb_raw_write(sc, data, sizeof(data), USB_MS_HZ);
1001         bbb_detach(sc);
1002         return (err);
1003 }
1004