35#ifdef USB_GLOBAL_INCLUDE_FILE
36#include USB_GLOBAL_INCLUDE_FILE
38#include <sys/stdint.h>
39#include <sys/stddef.h>
44#include <sys/kernel.h>
46#include <sys/module.h>
49#include <sys/condvar.h>
50#include <sys/sysctl.h>
52#include <sys/unistd.h>
53#include <sys/callout.h>
54#include <sys/malloc.h>
61#define USB_DEBUG_VAR usb_debug
90#define SCSI_MAX_LEN MAX(SCSI_FIXED_BLOCK_SIZE, USB_MSCTEST_BULK_SIZE)
91#define SCSI_INQ_LEN 0x24
92#define SCSI_SENSE_LEN 0xFF
93#define SCSI_FIXED_BLOCK_SIZE 512
101 0x01, 0x01, 0x01, 0x01, 0x00, 0x00 };
105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106 0x00, 0x00, 0x00, 0x00 };
108 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109 0x00, 0x00, 0x00, 0x00 };
112 0x00, 0x00, 0x00, 0x00 };
114 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
116 0x00, 0x00, 0x00, 0x00 };
120#ifndef USB_MSCTEST_BULK_SIZE
121#define USB_MSCTEST_BULK_SIZE 64
124#define ERR_CSW_FAILED -1
129#define CBWSIGNATURE 0x43425355
133#define CBWFLAGS_OUT 0x00
134#define CBWFLAGS_IN 0x80
137#define CBWCDBLENGTH 16
144#define CSWSIGNATURE 0x53425355
148#define CSWSTATUS_GOOD 0x0
149#define CSWSTATUS_FAILED 0x1
150#define CSWSTATUS_PHASE 0x2
201 .bufsize =
sizeof(
struct bbb_cbw),
211 .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,},
230 .flags = {.ext_buffer = 1,.proxy_buffer = 1,},
248 .bufsize =
sizeof(
struct bbb_csw),
249 .flags = {.short_xfer_ok = 1,},
261 .flags = {.ext_buffer = 1,.proxy_buffer = 1,},
279 sc->
state = xfer_index;
285 uint8_t next_xfer, uint8_t stall_xfer)
327 DPRINTFN(0,
"Truncating long command\n");
360 DPRINTF(
"max_bulk=%d, data_rem=%d\n",
412 DPRINTF(
"max_bulk=%d, data_rem=%d\n",
474 DPRINTF(
"Failed to read CSW: %s, try %d\n",
507 DPRINTF(
"max_bulk=%d, data_rem=%d\n",
551 DPRINTFN(1,
"SCSI cmd = %*D\n", (
int)
cmd_len, (
char *)sc->
cbw->
CBWCDB,
":");
557 cv_wait(&sc->
cv, &sc->
mtx);
581 DPRINTFN(1,
"BULK DATA = %*D\n", (
int)
data_len,
587 cv_wait(&sc->
cv, &sc->
mtx);
603#if USB_HAVE_MSCTEST_DETACH
627 switch (
id->bInterfaceClass) {
629 switch (
id->bInterfaceSubClass) {
638 switch (
id->bInterfaceProtocol) {
649 switch (
id->bInterfaceSubClass) {
662 sc = malloc(
sizeof(*sc), M_USB, M_WAITOK | M_ZERO);
663 mtx_init(&sc->
mtx,
"USB autoinstall", NULL, MTX_DEF);
664 cv_init(&sc->
cv,
"WBBB");
667 nconfig, sc, &sc->
mtx);
672 switch (
id->bInterfaceClass) {
694 mtx_destroy(&sc->
mtx);
726 if (err == 0 && sc->
actlen > 0) {
727 sid_type = sc->
buffer[0] & 0x1F;
728 if (sid_type == 0x05)
750 req.wIndex[0] = iface_index;
761#define USB_ADD_QUIRK(udev, any, which) do { \
762 if (usb_get_manufacturer(udev) != NULL && usb_get_product(udev) != NULL) { \
763 DPRINTFN(0, #which " set for USB mass storage device %s %s (0x%04x:0x%04x)\n", \
764 usb_get_manufacturer(udev), \
765 usb_get_product(udev), \
766 UGETW(udev->ddesc.idVendor), \
767 UGETW(udev->ddesc.idProduct)); \
769 DPRINTFN(0, #which " set for USB mass storage device, 0x%04x:0x%04x\n", \
770 UGETW(udev->ddesc.idVendor), \
771 UGETW(udev->ddesc.idProduct)); \
773 usbd_add_dynamic_quirk(udev, which); \
783 uint8_t is_no_direct;
802 DPRINTF(
"Device has only got one LUN.\n");
807 for (timeout = 4; timeout != 0; timeout--) {
812 if (err == 0 && sc->
actlen > 0) {
813 sid_type = sc->
buffer[0] & 0x1F;
814 if (sid_type == 0x00)
818 DPRINTF(
"Device is not responding "
819 "properly to SCSI INQUIRY command.\n");
826 DPRINTF(
"Device is not direct access.\n");
894 goto retry_sync_cache;
922 DPRINTF(
"Inquiry = %d\n", err);
933 DPRINTF(
"Request sense = %d\n", err);
1018 DPRINTF(
"Unknown eject method (%d)\n", method);
1032 static const uint8_t
data[3] = { 0x1b, 0x5a, 0x01 };
1046 uint32_t lba, uint32_t blocks,
void *
buffer)
1059 cmd[7] = blocks >> 8;
1077 uint32_t lba, uint32_t blocks,
void *
buffer)
1090 cmd[7] = blocks >> 8;
1108 uint32_t *lba_last, uint32_t *block_size)
uByte CBWCDB[CBWCDBLENGTH]
uDWord dCBWDataTransferLength
usb_timeout_t data_timeout
usb_frlength_t buffer_size
struct usb_xfer * xfer[ST_MAX]
struct usb_interface_descriptor * idesc
#define UT_READ_CLASS_INTERFACE
#define USB_UNCONFIG_INDEX
#define UISUBCLASS_SFF8070I
#define UISUBCLASS_SFF8020I
#define UIPROTO_MASS_BBB_OLD
uint8_t usbd_enum_lock(struct usb_device *udev)
usb_error_t usbd_set_config_index(struct usb_device *udev, uint8_t index)
void usbd_enum_unlock(struct usb_device *udev)
void usb_detach_device(struct usb_device *udev, uint8_t iface_index, uint8_t flag)
struct usb_interface * usbd_get_iface(struct usb_device *udev, uint8_t iface_index)
const char * usbd_errstr(usb_error_t err)
static uint8_t scsi_sync_cache[]
static void bbb_done(struct bbb_transfer *, int)
int usb_iface_is_cdrom(struct usb_device *udev, uint8_t iface_index)
#define USB_ADD_QUIRK(udev, any, which)
usb_error_t usb_dymo_eject(struct usb_device *udev, uint8_t iface_index)
static uint8_t scsi_read_capacity[]
static uint8_t scsi_prevent_removal[]
static uint8_t scsi_cmotech_eject[]
static uint8_t scsi_rezero_init[]
static uint8_t scsi_stop_unit[]
static void bbb_data_clear_stall_callback(struct usb_xfer *, uint8_t, uint8_t)
static usb_callback_t bbb_raw_write_callback
static uint8_t scsi_start_unit[]
static uint8_t scsi_huawei_eject[]
static uint8_t scsi_huawei_eject2[]
static uint8_t scsi_allow_removal[]
static usb_callback_t bbb_command_callback
static const struct usb_config bbb_config[ST_MAX]
static void bbb_detach(struct bbb_transfer *)
static int bbb_raw_write(struct bbb_transfer *sc, const void *data_ptr, size_t data_len, usb_timeout_t data_timeout)
static int bbb_command_start(struct bbb_transfer *, uint8_t, uint8_t, void *, size_t, void *, size_t, usb_timeout_t)
static uint8_t scsi_tct_eject[]
static usb_callback_t bbb_data_rd_cs_callback
static const struct usb_config bbb_raw_config[1]
static uint8_t scsi_test_unit_ready[]
static struct bbb_transfer * bbb_attach(struct usb_device *, uint8_t, uint8_t)
static uint8_t scsi_ztestor_eject[]
usb_error_t usb_msc_write_10(struct usb_device *udev, uint8_t iface_index, uint32_t lba, uint32_t blocks, void *buffer)
static usb_callback_t bbb_status_callback
usb_error_t usb_msc_eject(struct usb_device *udev, uint8_t iface_index, int method)
#define SCSI_FIXED_BLOCK_SIZE
usb_error_t usb_msc_read_10(struct usb_device *udev, uint8_t iface_index, uint32_t lba, uint32_t blocks, void *buffer)
static usb_callback_t bbb_data_write_callback
static uint8_t scsi_inquiry[]
static usb_callback_t bbb_data_read_callback
static void bbb_transfer_start(struct bbb_transfer *, uint8_t)
static usb_callback_t bbb_data_wr_cs_callback
static uint8_t scsi_request_sense[]
static uint8_t usb_msc_get_max_lun(struct usb_device *udev, uint8_t iface_index)
usb_error_t usb_msc_read_capacity(struct usb_device *udev, uint8_t iface_index, uint32_t *lba_last, uint32_t *block_size)
usb_error_t usb_msc_auto_quirk(struct usb_device *udev, uint8_t iface_index, const struct usb_attach_arg *uaa)
@ UQ_MSC_NO_TEST_UNIT_READY
@ UQ_MSC_NO_PREVENT_ALLOW
uint8_t usb_test_quirk(const struct usb_attach_arg *uaa, uint16_t quirk)
usb_error_t usbd_req_re_enumerate(struct usb_device *udev, struct mtx *mtx)
void usbd_xfer_set_timeout(struct usb_xfer *xfer, int t)
void usbd_transfer_submit(struct usb_xfer *xfer)
void usbd_transfer_unsetup(struct usb_xfer **pxfer, uint16_t n_setup)
void usbd_xfer_set_frame_data(struct usb_xfer *xfer, usb_frcount_t frindex, void *ptr, usb_frlength_t len)
void usbd_xfer_set_frame_len(struct usb_xfer *xfer, usb_frcount_t frindex, usb_frlength_t len)
uint8_t usbd_clear_stall_callback(struct usb_xfer *xfer1, struct usb_xfer *xfer2)
void * usbd_xfer_get_frame_buffer(struct usb_xfer *xfer, usb_frcount_t frindex)
usb_error_t usbd_transfer_setup(struct usb_device *udev, const uint8_t *ifaces, struct usb_xfer **ppxfer, const struct usb_config *setup_start, uint16_t n_setup, void *priv_sc, struct mtx *xfer_mtx)
void usbd_transfer_start(struct usb_xfer *xfer)
void * usbd_xfer_softc(struct usb_xfer *xfer)
void usbd_xfer_status(struct usb_xfer *xfer, int *actlen, int *sumlen, int *aframes, int *nframes)
usb_frlength_t usbd_xfer_max_len(struct usb_xfer *xfer)
uint8_t usbd_transfer_pending(struct usb_xfer *xfer)
void usb_pause_mtx(struct mtx *mtx, int timo)
#define USB_MTX_UNLOCK(_m)
#define USB_ST_TRANSFERRED
void() usb_callback_t(struct usb_xfer *, usb_error_t)
#define USB_GET_STATE(xfer)
#define usbd_do_request(u, m, r, d)