Index: sys/dev/usb/quirk/usb_quirk.h =================================================================== --- sys/dev/usb/quirk/usb_quirk.h +++ sys/dev/usb/quirk/usb_quirk.h @@ -119,5 +119,6 @@ }; uint8_t usb_test_quirk(const struct usb_attach_arg *uaa, uint16_t quirk); +extern const char *usb_quirk_str[USB_QUIRK_MAX]; #endif /* _USB_QUIRK_H_ */ Index: sys/dev/usb/quirk/usb_quirk.c =================================================================== --- sys/dev/usb/quirk/usb_quirk.c +++ sys/dev/usb/quirk/usb_quirk.c @@ -595,7 +595,7 @@ #undef USB_QUIRK_VP #undef USB_QUIRK -static const char *usb_quirk_str[USB_QUIRK_MAX] = { +const char *usb_quirk_str[USB_QUIRK_MAX] = { [UQ_NONE] = "UQ_NONE", [UQ_MATCH_VENDOR_ONLY] = "UQ_MATCH_VENDOR_ONLY", [UQ_AUDIO_SWAP_LR] = "UQ_AUDIO_SWAP_LR", Index: sys/dev/usb/usb_device.c =================================================================== --- sys/dev/usb/usb_device.c +++ sys/dev/usb/usb_device.c @@ -2053,7 +2053,7 @@ * Try to figure out if there are any MSC quirks we * should apply automatically: */ - err = usb_msc_auto_quirk(udev, 0); + err = usb_msc_auto_quirk(udev, 0, uaa); if (err != 0) { set_config_failed = 1; Index: sys/dev/usb/usb_msctest.h =================================================================== --- sys/dev/usb/usb_msctest.h +++ sys/dev/usb/usb_msctest.h @@ -44,7 +44,7 @@ usb_error_t usb_msc_eject(struct usb_device *udev, uint8_t iface_index, int method); usb_error_t usb_msc_auto_quirk(struct usb_device *udev, - uint8_t iface_index); + uint8_t iface_index, struct usb_attach_arg uaa); usb_error_t usb_msc_read_10(struct usb_device *udev, uint8_t iface_index, uint32_t lba, uint32_t blocks, void *buffer); Index: sys/dev/usb/usb_msctest.c =================================================================== --- sys/dev/usb/usb_msctest.c +++ sys/dev/usb/usb_msctest.c @@ -29,9 +29,6 @@ /* * The following file contains code that will detect USB autoinstall * disks. - * - * TODO: Potentially we could add code to automatically detect USB - * mass storage quirks for not supported SCSI commands! */ #ifdef USB_GLOBAL_INCLUDE_FILE @@ -70,6 +67,7 @@ #include #include #include +#include #include #endif /* USB_GLOBAL_INCLUDE_FILE */ @@ -118,6 +116,13 @@ static uint8_t scsi_prevent_removal[] = { 0x1e, 0, 0, 0, 1, 0 }; static uint8_t scsi_allow_removal[] = { 0x1e, 0, 0, 0, 0, 0 }; +/** + * The first byte refers to the position in usb_quirk_str[], + * found in usb_quirk.c + */ +static uint8_t scsi_quirk_no_test_unit_ready[] = { 0x1b, 0, 0, 0, 0, 0 }; +static uint8_t scsi_quirk_no_sync_cache[] = { 0x22, 0, 0, 0, 0, 0 }; + #ifndef USB_MSCTEST_BULK_SIZE #define USB_MSCTEST_BULK_SIZE 64 /* dummy */ #endif @@ -760,7 +765,8 @@ } usb_error_t -usb_msc_auto_quirk(struct usb_device *udev, uint8_t iface_index) +usb_msc_auto_quirk(struct usb_device *udev, uint8_t iface_index, + struct usb_attach_arg uaa) { struct bbb_transfer *sc; uint8_t timeout; @@ -836,6 +842,40 @@ timeout = 1; + if (usb_test_quirk(&uaa, UQ_MSC_NO_TEST_UNIT_READY) == 0) { + err = bbb_command_start(sc, DIR_NONE, 0, NULL, 0, + &scsi_quirk_no_test_unit_ready, sizeof(scsi_quirk_no_test_unit_ready), + USB_MS_HZ); + if (err == 0) { + printf("Applying dynamic quirk %s for USB mass storage device %s %s (0x%x:0x%x)\n", + usb_quirk_str[UQ_MSC_NO_TEST_UNIT_READY], + udev->manufacturer, + udev->product, + UGETW(udev->ddesc.idVendor), + UGETW(udev->ddesc.idProduct) + ); + usbd_add_dynamic_quirk(udev, UQ_MSC_NO_TEST_UNIT_READY); + /* fall through */ + } + } + + if (usb_test_quirk(&uaa, UQ_MSC_NO_SYNC_CACHE) == 0) { + err = bbb_command_start(sc, DIR_NONE, 0, NULL, 0, + &scsi_quirk_no_sync_cache, sizeof(scsi_quirk_no_sync_cache), + USB_MS_HZ); + if (err == ERR_CSW_FAILED) { + printf("Applying dynamic quirk %s for USB mass storage device %s %s (0x%x:0x%x)\n", + usb_quirk_str[UQ_MSC_NO_SYNC_CACHE], + udev->manufacturer, + udev->product, + UGETW(udev->ddesc.idVendor), + UGETW(udev->ddesc.idProduct) + ); + usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE); + goto error; + } + } + retry_sync_cache: err = bbb_command_start(sc, DIR_IN, 0, NULL, 0, &scsi_sync_cache, sizeof(scsi_sync_cache), @@ -917,9 +957,7 @@ DPRINTF("Device did not respond, enabling all quirks\n"); - usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE); usbd_add_dynamic_quirk(udev, UQ_MSC_NO_PREVENT_ALLOW); - usbd_add_dynamic_quirk(udev, UQ_MSC_NO_TEST_UNIT_READY); /* Need to re-enumerate the device */ usbd_req_re_enumerate(udev, NULL);