summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2011-09-02 18:50:44 +0000
committerhselasky <hselasky@FreeBSD.org>2011-09-02 18:50:44 +0000
commit8335f4b89d8e67c285a31d6b11a370185ce0b949 (patch)
treec6f2687acbbed316803ce152679d1c321f8174e7
parent56a7a5d12f3bd0a91a39b86bb619324e35c2c6b9 (diff)
downloadFreeBSD-src-8335f4b89d8e67c285a31d6b11a370185ce0b949.zip
FreeBSD-src-8335f4b89d8e67c285a31d6b11a370185ce0b949.tar.gz
This patch adds automatic detection of USB mass storage devices
which does not support the no synchronize cache SCSI command. The __FreeBSD_version version macro has been bumped and external kernel modules needs to be recompiled after this patch. Approved by: re (kib) MFC after: 1 week PR: usb/160299
-rw-r--r--sys/dev/usb/quirk/usb_quirk.c25
-rw-r--r--sys/dev/usb/storage/umass.c6
-rw-r--r--sys/dev/usb/usb_device.c34
-rw-r--r--sys/dev/usb/usb_device.h1
-rw-r--r--sys/dev/usb/usb_dynamic.c14
-rw-r--r--sys/dev/usb/usb_dynamic.h1
-rw-r--r--sys/dev/usb/usb_freebsd.h2
-rw-r--r--sys/dev/usb/usb_msctest.c93
-rw-r--r--sys/dev/usb/usb_msctest.h2
-rw-r--r--sys/dev/usb/usbdi.h3
-rw-r--r--sys/sys/param.h2
11 files changed, 149 insertions, 34 deletions
diff --git a/sys/dev/usb/quirk/usb_quirk.c b/sys/dev/usb/quirk/usb_quirk.c
index e54b908..d1bd0ee 100644
--- a/sys/dev/usb/quirk/usb_quirk.c
+++ b/sys/dev/usb/quirk/usb_quirk.c
@@ -148,12 +148,10 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
UQ_MSC_FORCE_PROTO_SCSI),
USB_QUIRK(AIPTEK, POCKETCAM3M, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI),
- USB_QUIRK(AIPTEK2, SUNPLUS_TECH, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(ALCOR, SDCR_6335, 0x0000, 0xffff, UQ_MSC_NO_TEST_UNIT_READY,
UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(ALCOR, SDCR_6362, 0x0000, 0xffff, UQ_MSC_NO_TEST_UNIT_READY,
UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(ALCOR, AU6390, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(ALCOR, UMCR_9361, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
USB_QUIRK(ALCOR, TRANSCEND, 0x0000, 0xffff, UQ_MSC_NO_GETMAXLUN,
@@ -173,14 +171,12 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(CENTURY, EX35QUAT, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ,
UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE),
- USB_QUIRK(CENTURY, EX35SW4_SB4, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(CYPRESS, XX6830XX, 0x0000, 0xffff, UQ_MSC_NO_GETMAXLUN,
UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(DESKNOTE, UCR_61S2B, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI),
USB_QUIRK(DMI, CFSM_RW, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI,
UQ_MSC_NO_GETMAXLUN),
- USB_QUIRK(DMI, DISK, 0x000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(EPSON, STYLUS_875DC, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
USB_QUIRK(EPSON, STYLUS_895, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
@@ -188,7 +184,6 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(FEIYA, 5IN1, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI),
USB_QUIRK(FREECOM, DVD, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
- USB_QUIRK(FREECOM, HDD, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(FUJIPHOTO, MASS0100, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI_I,
UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_RS_CLEAR_UA, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(GENESYS, GL641USB2IDE, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
@@ -232,7 +227,6 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(IOMEGA, ZIP100, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI,
UQ_MSC_NO_TEST_UNIT_READY), /* XXX ZIP drives can also use ATAPI */
- USB_QUIRK(JMICRON, JM20336, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(JMICRON, JM20337, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI,
UQ_MSC_NO_SYNC_CACHE),
@@ -279,8 +273,6 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
UQ_MSC_FORCE_PROTO_ATAPI),
USB_QUIRK(MYSON, HEDEN, 0x0000, 0xffff, UQ_MSC_IGNORE_RESIDUE,
UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(MYSON, HEDEN_8813, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(MYSON, STARREADER, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(NEODIO, ND3260, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ),
USB_QUIRK(NETAC, CF_CARD, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
@@ -317,7 +309,6 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(PANASONIC, KXLCB35AN, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI),
USB_QUIRK(PANASONIC, LS120CAM, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_UFI),
- USB_QUIRK(PHILIPS, SPE3030CC, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(PLEXTOR, 40_12_40U, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_TEST_UNIT_READY),
USB_QUIRK(PNY, ATTACHE2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
@@ -328,7 +319,6 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK_VP(USB_VENDOR_SAMSUNG_TECHWIN,
USB_PRODUCT_SAMSUNG_TECHWIN_DIGIMAX_410, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
- USB_QUIRK(SAMSUNG, YP_U4, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(SANDISK, SDDR05A, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_READ_CAP_OFFBY1,
UQ_MSC_NO_GETMAXLUN),
@@ -448,12 +438,6 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
UQ_MSC_FORCE_PROTO_ATAPI),
USB_QUIRK(MEIZU, M6_SL, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY, UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(ACTIONS, MP4, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
- UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(ASUS, GMSC, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(CHIPSBANK, USBMEMSTICK, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(CHIPSBANK, USBMEMSTICK1, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(NEWLINK, USB2IDEBRIDGE, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
/* Non-standard USB MIDI devices */
USB_QUIRK(ROLAND, UM1, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
@@ -567,9 +551,9 @@ usb_test_quirk_by_info(const struct usbd_lookup_info *info, uint16_t quirk)
uint16_t x;
uint16_t y;
- if (quirk == UQ_NONE) {
- return (0);
- }
+ if (quirk == UQ_NONE)
+ goto done;
+
mtx_lock(&usb_quirk_mtx);
for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) {
@@ -603,7 +587,8 @@ usb_test_quirk_by_info(const struct usbd_lookup_info *info, uint16_t quirk)
break;
}
mtx_unlock(&usb_quirk_mtx);
- return (0);
+done:
+ return (usb_test_quirk_w(info, quirk));
}
static struct usb_quirk_entry *
diff --git a/sys/dev/usb/storage/umass.c b/sys/dev/usb/storage/umass.c
index 9292c84..41e98d5 100644
--- a/sys/dev/usb/storage/umass.c
+++ b/sys/dev/usb/storage/umass.c
@@ -1025,12 +1025,6 @@ umass_attach(device_t dev)
sc->cam_scsi_sense.opcode = REQUEST_SENSE;
sc->cam_scsi_test_unit_ready.opcode = TEST_UNIT_READY;
- /*
- * some devices need a delay after that the configuration value is
- * set to function properly:
- */
- usb_pause_mtx(NULL, hz);
-
/* register the SIM */
err = umass_cam_attach_sim(sc);
if (err) {
diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c
index 34f6265..3be9ba9 100644
--- a/sys/dev/usb/usb_device.c
+++ b/sys/dev/usb/usb_device.c
@@ -1239,7 +1239,9 @@ static void
usb_init_attach_arg(struct usb_device *udev,
struct usb_attach_arg *uaa)
{
- bzero(uaa, sizeof(*uaa));
+ uint8_t x;
+
+ memset(uaa, 0, sizeof(*uaa));
uaa->device = udev;
uaa->usb_mode = udev->flags.usb_mode;
@@ -1254,6 +1256,9 @@ usb_init_attach_arg(struct usb_device *udev,
uaa->info.bDeviceProtocol = udev->ddesc.bDeviceProtocol;
uaa->info.bConfigIndex = udev->curr_config_index;
uaa->info.bConfigNum = udev->curr_config_no;
+
+ for (x = 0; x != USB_MAX_AUTO_QUIRK; x++)
+ uaa->info.autoQuirk[x] = udev->autoQuirk[x];
}
/*------------------------------------------------------------------------*
@@ -1850,6 +1855,20 @@ repeat_set_config:
}
}
}
+ if (set_config_failed == 0 && config_index == 0 &&
+ usb_test_quirk(&uaa, UQ_MSC_NO_SYNC_CACHE) == 0) {
+
+ /*
+ * Try to figure out if there are any MSC quirks we
+ * should apply automatically:
+ */
+ err = usb_msc_auto_quirk(udev, 0);
+
+ if (err != 0) {
+ set_config_failed = 1;
+ goto repeat_set_config;
+ }
+ }
config_done:
DPRINTF("new dev (addr %d), udev=%p, parent_hub=%p\n",
@@ -2698,3 +2717,16 @@ usbd_set_pnpinfo(struct usb_device *udev, uint8_t iface_index, const char *pnpin
return (0); /* success */
}
+usb_error_t
+usbd_add_dynamic_quirk(struct usb_device *udev, uint16_t quirk)
+{
+ uint8_t x;
+
+ for (x = 0; x != USB_MAX_AUTO_QUIRK; x++) {
+ if (udev->autoQuirk[x] == 0) {
+ udev->autoQuirk[x] = quirk;
+ return (0); /* success */
+ }
+ }
+ return (USB_ERR_NOMEM);
+}
diff --git a/sys/dev/usb/usb_device.h b/sys/dev/usb/usb_device.h
index fe8bf8b..bde20b0 100644
--- a/sys/dev/usb/usb_device.h
+++ b/sys/dev/usb/usb_device.h
@@ -149,6 +149,7 @@ struct usb_device {
uint16_t power; /* mA the device uses */
uint16_t langid; /* language for strings */
+ uint16_t autoQuirk[USB_MAX_AUTO_QUIRK]; /* dynamic quirks */
uint8_t address; /* device addess */
uint8_t device_index; /* device index in "bus->devices" */
diff --git a/sys/dev/usb/usb_dynamic.c b/sys/dev/usb/usb_dynamic.c
index 1358b30..765ee4f 100644
--- a/sys/dev/usb/usb_dynamic.c
+++ b/sys/dev/usb/usb_dynamic.c
@@ -50,12 +50,12 @@
#include <dev/usb/usb_process.h>
#include <dev/usb/usb_device.h>
#include <dev/usb/usb_dynamic.h>
+#include <dev/usb/quirk/usb_quirk.h>
/* function prototypes */
static usb_handle_req_t usb_temp_get_desc_w;
static usb_temp_setup_by_index_t usb_temp_setup_by_index_w;
static usb_temp_unsetup_t usb_temp_unsetup_w;
-static usb_test_quirk_t usb_test_quirk_w;
static usb_quirk_ioctl_t usb_quirk_ioctl_w;
/* global variables */
@@ -72,9 +72,19 @@ usb_temp_setup_by_index_w(struct usb_device *udev, uint16_t index)
return (USB_ERR_INVAL);
}
-static uint8_t
+uint8_t
usb_test_quirk_w(const struct usbd_lookup_info *info, uint16_t quirk)
{
+ uint8_t x;
+
+ if (quirk == UQ_NONE)
+ return (0); /* no match */
+
+ for (x = 0; x != USB_MAX_AUTO_QUIRK; x++) {
+ if (info->autoQuirk[x] == quirk)
+ return (1); /* match */
+ }
+
return (0); /* no match */
}
diff --git a/sys/dev/usb/usb_dynamic.h b/sys/dev/usb/usb_dynamic.h
index 5684942..f1b2149 100644
--- a/sys/dev/usb/usb_dynamic.h
+++ b/sys/dev/usb/usb_dynamic.h
@@ -57,5 +57,6 @@ extern devclass_t usb_devclass_ptr;
void usb_temp_unload(void *);
void usb_quirk_unload(void *);
void usb_bus_unload(void *);
+usb_test_quirk_t usb_test_quirk_w;
#endif /* _USB_DYNAMIC_H_ */
diff --git a/sys/dev/usb/usb_freebsd.h b/sys/dev/usb/usb_freebsd.h
index ae69cdb..349e13e 100644
--- a/sys/dev/usb/usb_freebsd.h
+++ b/sys/dev/usb/usb_freebsd.h
@@ -68,6 +68,8 @@
#define USB_EP0_BUFSIZE 1024 /* bytes */
#define USB_CS_RESET_LIMIT 20 /* failures = 20 * 50 ms = 1sec */
+#define USB_MAX_AUTO_QUIRK 4 /* maximum number of dynamic quirks */
+
typedef uint32_t usb_timeout_t; /* milliseconds */
typedef uint32_t usb_frlength_t; /* bytes */
typedef uint32_t usb_frcount_t; /* units */
diff --git a/sys/dev/usb/usb_msctest.c b/sys/dev/usb/usb_msctest.c
index 0b6024b..061c3d3 100644
--- a/sys/dev/usb/usb_msctest.c
+++ b/sys/dev/usb/usb_msctest.c
@@ -96,6 +96,8 @@ static uint8_t scsi_huawei_eject[] = { 0x11, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
static uint8_t scsi_tct_eject[] = { 0x06, 0xf5, 0x04, 0x02, 0x52, 0x70 };
+static uint8_t scsi_sync_cache[] = { 0x35, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
#define BULK_SIZE 64 /* dummy */
#define ERR_CSW_FAILED -1
@@ -163,7 +165,7 @@ static void bbb_done(struct bbb_transfer *, int);
static void bbb_transfer_start(struct bbb_transfer *, uint8_t);
static void bbb_data_clear_stall_callback(struct usb_xfer *, uint8_t,
uint8_t);
-static uint8_t bbb_command_start(struct bbb_transfer *, uint8_t, uint8_t,
+static int bbb_command_start(struct bbb_transfer *, uint8_t, uint8_t,
void *, size_t, void *, size_t, usb_timeout_t);
static struct bbb_transfer *bbb_attach(struct usb_device *, uint8_t);
static void bbb_detach(struct bbb_transfer *);
@@ -454,7 +456,7 @@ bbb_status_callback(struct usb_xfer *xfer, usb_error_t error)
* 0: Success
* Else: Failure
*------------------------------------------------------------------------*/
-static uint8_t
+static int
bbb_command_start(struct bbb_transfer *sc, uint8_t dir, uint8_t lun,
void *data_ptr, size_t data_len, void *cmd_ptr, size_t cmd_len,
usb_timeout_t data_timeout)
@@ -566,9 +568,10 @@ int
usb_iface_is_cdrom(struct usb_device *udev, uint8_t iface_index)
{
struct bbb_transfer *sc;
- usb_error_t err;
- uint8_t timeout, is_cdrom;
+ uint8_t timeout;
+ uint8_t is_cdrom;
uint8_t sid_type;
+ int err;
sc = bbb_attach(udev, iface_index);
if (sc == NULL)
@@ -595,6 +598,88 @@ usb_iface_is_cdrom(struct usb_device *udev, uint8_t iface_index)
}
usb_error_t
+usb_msc_auto_quirk(struct usb_device *udev, uint8_t iface_index)
+{
+ struct bbb_transfer *sc;
+ uint8_t timeout;
+ uint8_t is_no_direct;
+ uint8_t sid_type;
+ int err;
+
+ sc = bbb_attach(udev, iface_index);
+ if (sc == NULL)
+ return (0);
+
+ /*
+ * Some devices need a delay after that the configuration
+ * value is set to function properly:
+ */
+ usb_pause_mtx(NULL, hz);
+
+ is_no_direct = 1;
+ for (timeout = 4; timeout; timeout--) {
+ err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
+ SCSI_INQ_LEN, &scsi_inquiry, sizeof(scsi_inquiry),
+ USB_MS_HZ);
+
+ if (err == 0 && sc->actlen > 0) {
+ sid_type = sc->buffer[0] & 0x1F;
+ if (sid_type == 0x00)
+ is_no_direct = 0;
+ break;
+ } else if (err != ERR_CSW_FAILED)
+ break; /* non retryable error */
+ usb_pause_mtx(NULL, hz);
+ }
+
+ if (is_no_direct) {
+ DPRINTF("Device is not direct access.\n");
+ 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 (err != 0) {
+
+ if (err != ERR_CSW_FAILED)
+ goto error;
+ }
+
+ err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
+ &scsi_sync_cache, sizeof(scsi_sync_cache),
+ USB_MS_HZ);
+
+ if (err != 0) {
+
+ 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);
+ }
+
+done:
+ bbb_detach(sc);
+ return (0);
+
+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_TEST_UNIT_READY);
+
+ /* Need to re-enumerate the device */
+ usbd_req_re_enumerate(udev, NULL);
+
+ return (USB_ERR_STALLED);
+}
+
+usb_error_t
usb_msc_eject(struct usb_device *udev, uint8_t iface_index, int method)
{
struct bbb_transfer *sc;
diff --git a/sys/dev/usb/usb_msctest.h b/sys/dev/usb/usb_msctest.h
index 807d5f5..e4a717f 100644
--- a/sys/dev/usb/usb_msctest.h
+++ b/sys/dev/usb/usb_msctest.h
@@ -40,5 +40,7 @@ int usb_iface_is_cdrom(struct usb_device *udev,
uint8_t iface_index);
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);
#endif /* _USB_MSCTEST_H_ */
diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h
index 8cdbc2d..6f89922 100644
--- a/sys/dev/usb/usbdi.h
+++ b/sys/dev/usb/usbdi.h
@@ -353,6 +353,7 @@ struct usbd_lookup_info {
uint16_t idVendor;
uint16_t idProduct;
uint16_t bcdDevice;
+ uint16_t autoQuirk[USB_MAX_AUTO_QUIRK];
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
@@ -475,6 +476,8 @@ void device_set_usb_desc(device_t dev);
void usb_pause_mtx(struct mtx *mtx, int _ticks);
usb_error_t usbd_set_pnpinfo(struct usb_device *udev,
uint8_t iface_index, const char *pnpinfo);
+usb_error_t usbd_add_dynamic_quirk(struct usb_device *udev,
+ uint16_t quirk);
const struct usb_device_id *usbd_lookup_id_by_info(
const struct usb_device_id *id, usb_size_t sizeof_id,
diff --git a/sys/sys/param.h b/sys/sys/param.h
index 44005ae..41b9ff3 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 900042 /* Master, propagated to newvers */
+#define __FreeBSD_version 900043 /* Master, propagated to newvers */
#ifdef _KERNEL
#define P_OSREL_SIGSEGV 700004
OpenPOWER on IntegriCloud