diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c --- a/sys/dev/usb/usb_device.c +++ b/sys/dev/usb/usb_device.c @@ -2047,13 +2047,15 @@ } #if USB_HAVE_MSCTEST if (set_config_failed == 0 && config_index == 0 && + usb_test_quirk(&uaa, UQ_MSC_NO_PREVENT_ALLOW) == 0 && usb_test_quirk(&uaa, UQ_MSC_NO_SYNC_CACHE) == 0 && + usb_test_quirk(&uaa, UQ_MSC_NO_TEST_UNIT_READY) == 0 && usb_test_quirk(&uaa, UQ_MSC_NO_GETMAXLUN) == 0) { /* * 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; diff --git a/sys/dev/usb/usb_msctest.h b/sys/dev/usb/usb_msctest.h --- a/sys/dev/usb/usb_msctest.h +++ b/sys/dev/usb/usb_msctest.h @@ -2,7 +2,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. + * Copyright (c) 2008-2022 Hans Petter Selasky. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -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, const 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); diff --git a/sys/dev/usb/usb_msctest.c b/sys/dev/usb/usb_msctest.c --- a/sys/dev/usb/usb_msctest.c +++ b/sys/dev/usb/usb_msctest.c @@ -2,7 +2,8 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2008,2011 Hans Petter Selasky. All rights reserved. + * Copyright (c) 2008-2022 Hans Petter Selasky. + * Copyright (c) 2021-2022 Idwer Vollering. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,9 +30,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 @@ -759,8 +757,24 @@ return (buf); } +#define USB_ADD_QUIRK(udev, which) do { \ + if (usb_get_manufacturer(udev) != NULL && usb_get_product(udev) != NULL) { \ + DPRINTFN(0, "Applying dynamic quirk " #which " for USB mass storage device %s %s (0x%04x:0x%04x)\n", \ + usb_get_manufacturer(udev), \ + usb_get_product(udev), \ + UGETW(udev->ddesc.idVendor), \ + UGETW(udev->ddesc.idProduct)); \ + } else { \ + DPRINTF(0, "Applying dynamic quirk " #which " for USB mass storage device, 0x%04x:0x%04x\n", \ + UGETW(udev->ddesc.idVendor), \ + UGETW(udev->ddesc.idProduct)); \ + } \ + usbd_add_dynamic_quirk(udev, which); \ +} while (0) + 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, + const struct usb_attach_arg *uaa) { struct bbb_transfer *sc; uint8_t timeout; @@ -807,37 +821,40 @@ goto done; } - err = bbb_command_start(sc, DIR_IN, 0, NULL, 0, - &scsi_test_unit_ready, sizeof(scsi_test_unit_ready), - USB_MS_HZ); + if (usb_test_quirk(uaa, UQ_MSC_NO_TEST_UNIT_READY) == 0) { + err = bbb_command_start(sc, DIR_IN, 0, NULL, 0, + &scsi_test_unit_ready, sizeof(scsi_test_unit_ready), + USB_MS_HZ); - if (err != 0) { - if (err != ERR_CSW_FAILED) - goto error; - DPRINTF("Test unit ready failed\n"); + if (err != 0) { + if (err != ERR_CSW_FAILED) + goto error; + USB_ADD_QUIRK(udev, UQ_MSC_NO_TEST_UNIT_READY); + } } - err = bbb_command_start(sc, DIR_OUT, 0, NULL, 0, - &scsi_prevent_removal, sizeof(scsi_prevent_removal), - USB_MS_HZ); - - if (err == 0) { - err = bbb_command_start(sc, DIR_OUT, 0, NULL, 0, - &scsi_allow_removal, sizeof(scsi_allow_removal), + if (usb_test_quirk(uaa, UQ_MSC_NO_PREVENT_ALLOW) == 0) { + err = bbb_command_start(sc, DIR_NONE, 0, NULL, 0, + &scsi_prevent_removal, sizeof(scsi_prevent_removal), USB_MS_HZ); - } - if (err != 0) { - if (err != ERR_CSW_FAILED) - goto error; - DPRINTF("Device doesn't handle prevent and allow removal\n"); - usbd_add_dynamic_quirk(udev, UQ_MSC_NO_PREVENT_ALLOW); + if (err == 0) { + err = bbb_command_start(sc, DIR_NONE, 0, NULL, 0, + &scsi_allow_removal, sizeof(scsi_allow_removal), + USB_MS_HZ); + } + + if (err != 0) { + if (err != ERR_CSW_FAILED) + goto error; + USB_ADD_QUIRK(udev, UQ_MSC_NO_PREVENT_ALLOW); + } } timeout = 1; retry_sync_cache: - err = bbb_command_start(sc, DIR_IN, 0, NULL, 0, + err = bbb_command_start(sc, DIR_NONE, 0, NULL, 0, &scsi_sync_cache, sizeof(scsi_sync_cache), USB_MS_HZ); @@ -845,9 +862,7 @@ if (err != ERR_CSW_FAILED) goto error; - DPRINTF("Device doesn't handle synchronize cache\n"); - - usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE); + USB_ADD_QUIRK(udev, UQ_MSC_NO_SYNC_CACHE); } else { /* * Certain Kingston memory sticks fail the first @@ -872,11 +887,7 @@ if (timeout--) goto retry_sync_cache; - DPRINTF("Device most likely doesn't " - "handle synchronize cache\n"); - - usbd_add_dynamic_quirk(udev, - UQ_MSC_NO_SYNC_CACHE); + USB_ADD_QUIRK(udev, UQ_MSC_NO_SYNC_CACHE); } else { if (err != ERR_CSW_FAILED) goto error; @@ -915,11 +926,9 @@ error: bbb_detach(sc); - 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); + USB_ADD_QUIRK(udev, UQ_MSC_NO_SYNC_CACHE); + USB_ADD_QUIRK(udev, UQ_MSC_NO_PREVENT_ALLOW); + USB_ADD_QUIRK(udev, UQ_MSC_NO_TEST_UNIT_READY); /* Need to re-enumerate the device */ usbd_req_re_enumerate(udev, NULL);