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
This commit is contained in:
parent
ea96972a8b
commit
d46dc4ad74
@ -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 *
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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" */
|
||||
|
@ -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 */
|
||||
}
|
||||
|
||||
|
@ -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_ */
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
@ -594,6 +597,88 @@ usb_iface_is_cdrom(struct usb_device *udev, uint8_t iface_index)
|
||||
return (is_cdrom);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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_ */
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user