PERFORCE change 151947 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Sun Oct 26 13:28:34 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=151947
Change 151947 by hselasky at hselasky_laptop001 on 2008/10/26 13:28:23
Add support for dynamic USB quirks - final step.
Affected files ...
.. //depot/projects/usb/src/lib/libusb20/libusb20.h#6 edit
.. //depot/projects/usb/src/lib/libusb20/libusb20_ugen20.c#6 edit
.. //depot/projects/usb/src/sys/dev/usb2/core/usb2_dev.c#37 edit
.. //depot/projects/usb/src/sys/dev/usb2/core/usb2_dynamic.c#4 edit
.. //depot/projects/usb/src/sys/dev/usb2/core/usb2_dynamic.h#4 edit
.. //depot/projects/usb/src/sys/dev/usb2/include/usb2_ioctl.h#21 edit
.. //depot/projects/usb/src/sys/dev/usb2/quirk/usb2_quirk.c#7 edit
.. //depot/projects/usb/src/usr.sbin/usbconfig/dump.c#6 edit
.. //depot/projects/usb/src/usr.sbin/usbconfig/usbconfig.c#3 edit
Differences ...
==== //depot/projects/usb/src/lib/libusb20/libusb20.h#6 (text+ko) ====
@@ -189,9 +189,11 @@
struct libusb20_quirk {
uint16_t vid; /* vendor ID */
uint16_t pid; /* product ID */
+ uint16_t bcdDeviceLow; /* low revision value, inclusive */
+ uint16_t bcdDeviceHigh; /* high revision value, inclusive */
uint16_t reserved[2]; /* for the future */
- char quirkname[64 - 8]; /* quirk name including terminating
- * zero */
+ /* quirk name, UQ_XXX, including terminating zero */
+ char quirkname[64 - 12];
};
/* USB transfer operations */
==== //depot/projects/usb/src/lib/libusb20/libusb20_ugen20.c#6 (text+ko) ====
@@ -936,28 +936,98 @@
ugen20_root_get_dev_quirk(struct libusb20_backend *pbe,
uint16_t index, struct libusb20_quirk *pq)
{
- return (LIBUSB20_ERROR_NOT_SUPPORTED);
+ struct usb2_gen_quirk q;
+ int err;
+
+ memset(&q, 0, sizeof(q));
+
+ q.index = index;
+
+ err = ugen20_be_ioctl(USB_DEV_QUIRK_GET, &q);
+
+ if (err) {
+ if (errno == EINVAL) {
+ return (LIBUSB20_ERROR_NOT_FOUND);
+ }
+ } else {
+ pq->vid = q.vid;
+ pq->pid = q.pid;
+ pq->bcdDeviceLow = q.bcdDeviceLow;
+ pq->bcdDeviceHigh = q.bcdDeviceHigh;
+ strlcpy(pq->quirkname, q.quirkname, sizeof(pq->quirkname));
+ }
+ return (err);
}
static int
ugen20_root_get_quirk_name(struct libusb20_backend *pbe, uint16_t index,
struct libusb20_quirk *pq)
{
- return (LIBUSB20_ERROR_NOT_SUPPORTED);
+ struct usb2_gen_quirk q;
+ int err;
+
+ memset(&q, 0, sizeof(q));
+
+ q.index = index;
+
+ err = ugen20_be_ioctl(USB_QUIRK_NAME_GET, &q);
+
+ if (err) {
+ if (errno == EINVAL) {
+ return (LIBUSB20_ERROR_NOT_FOUND);
+ }
+ } else {
+ strlcpy(pq->quirkname, q.quirkname, sizeof(pq->quirkname));
+ }
+ return (err);
}
static int
ugen20_root_add_dev_quirk(struct libusb20_backend *pbe,
struct libusb20_quirk *pq)
{
- return (LIBUSB20_ERROR_NOT_SUPPORTED);
+ struct usb2_gen_quirk q;
+ int err;
+
+ memset(&q, 0, sizeof(q));
+
+ q.vid = pq->vid;
+ q.pid = pq->pid;
+ q.bcdDeviceLow = pq->bcdDeviceLow;
+ q.bcdDeviceHigh = pq->bcdDeviceHigh;
+ strlcpy(q.quirkname, pq->quirkname, sizeof(q.quirkname));
+
+ err = ugen20_be_ioctl(USB_DEV_QUIRK_ADD, &q);
+ if (err) {
+ if (errno == ENOMEM) {
+ return (LIBUSB20_ERROR_NO_MEM);
+ }
+ }
+ return (err);
}
static int
ugen20_root_remove_dev_quirk(struct libusb20_backend *pbe,
struct libusb20_quirk *pq)
{
- return (LIBUSB20_ERROR_NOT_SUPPORTED);
+ struct usb2_gen_quirk q;
+ int err;
+
+ memset(&q, 0, sizeof(q));
+
+ q.vid = pq->vid;
+ q.pid = pq->pid;
+ q.bcdDeviceLow = pq->bcdDeviceLow;
+ q.bcdDeviceHigh = pq->bcdDeviceHigh;
+ strlcpy(q.quirkname, pq->quirkname, sizeof(q.quirkname));
+
+ err = ugen20_be_ioctl(USB_DEV_QUIRK_REMOVE, &q);
+ if (err) {
+ if (errno == EINVAL) {
+ return (LIBUSB20_ERROR_NOT_FOUND);
+ }
+ }
+ return (err);
}
static int
==== //depot/projects/usb/src/sys/dev/usb2/core/usb2_dev.c#37 (text+ko) ====
@@ -1302,6 +1302,12 @@
case USB_GET_ROOT_PERM:
err = usb2_get_perm(u.udp, 0);
break;
+ case USB_DEV_QUIRK_GET:
+ case USB_QUIRK_NAME_GET:
+ case USB_DEV_QUIRK_ADD:
+ case USB_DEV_QUIRK_REMOVE:
+ err = usb2_quirk_ioctl_p(cmd, data, fflag, td);
+ break;
default:
err = ENOTTY;
break;
==== //depot/projects/usb/src/sys/dev/usb2/core/usb2_dynamic.c#4 (text+ko) ====
@@ -39,12 +39,14 @@
static usb2_temp_setup_by_index_t usb2_temp_setup_by_index_w;
static usb2_temp_unsetup_t usb2_temp_unsetup_w;
static usb2_test_quirk_t usb2_test_quirk_w;
+static usb2_quirk_ioctl_t usb2_quirk_ioctl_w;
/* global variables */
usb2_temp_get_desc_t *usb2_temp_get_desc_p = &usb2_temp_get_desc_w;
usb2_temp_setup_by_index_t *usb2_temp_setup_by_index_p = &usb2_temp_setup_by_index_w;
usb2_temp_unsetup_t *usb2_temp_unsetup_p = &usb2_temp_unsetup_w;
usb2_test_quirk_t *usb2_test_quirk_p = &usb2_test_quirk_w;
+usb2_quirk_ioctl_t *usb2_quirk_ioctl_p = &usb2_quirk_ioctl_w;
devclass_t usb2_devclass_ptr = NULL;
static usb2_error_t
@@ -59,6 +61,12 @@
return (0); /* no match */
}
+static int
+usb2_quirk_ioctl_w(unsigned long cmd, caddr_t data, int fflag, struct thread *td)
+{
+ return (ENOIOCTL);
+}
+
static void
usb2_temp_get_desc_w(struct usb2_device *udev, struct usb2_device_request *req, const void **pPtr, uint16_t *pLength)
{
@@ -86,6 +94,7 @@
/* reset function pointers */
usb2_test_quirk_p = &usb2_test_quirk_w;
+ usb2_quirk_ioctl_p = &usb2_quirk_ioctl_w;
/* wait for CPU to exit the loaded functions, if any */
==== //depot/projects/usb/src/sys/dev/usb2/core/usb2_dynamic.h#4 (text+ko) ====
@@ -37,6 +37,7 @@
typedef usb2_error_t (usb2_temp_setup_by_index_t)(struct usb2_device *udev, uint16_t index);
typedef uint8_t (usb2_test_quirk_t)(const struct usb2_lookup_info *info, uint16_t quirk);
+typedef int (usb2_quirk_ioctl_t)(unsigned long cmd, caddr_t data, int fflag, struct thread *td);
typedef void (usb2_temp_get_desc_t)(struct usb2_device *udev, struct usb2_device_request *req, const void **pPtr, uint16_t *pLength);
typedef void (usb2_temp_unsetup_t)(struct usb2_device *udev);
@@ -46,6 +47,7 @@
extern usb2_temp_setup_by_index_t *usb2_temp_setup_by_index_p;
extern usb2_temp_unsetup_t *usb2_temp_unsetup_p;
extern usb2_test_quirk_t *usb2_test_quirk_p;
+extern usb2_quirk_ioctl_t *usb2_quirk_ioctl_p;
extern devclass_t usb2_devclass_ptr;
/* function prototypes */
==== //depot/projects/usb/src/sys/dev/usb2/include/usb2_ioctl.h#21 (text+ko) ====
@@ -202,6 +202,20 @@
uint16_t iface_index;
};
+struct usb2_gen_quirk {
+ uint16_t index; /* Quirk Index */
+ uint16_t vid; /* Vendor ID */
+ uint16_t pid; /* Product ID */
+ uint16_t bcdDeviceLow; /* Low Device Revision */
+ uint16_t bcdDeviceHigh; /* High Device Revision */
+ uint16_t reserved[2];
+ /*
+ * String version of quirk including terminating zero. See UQ_XXX in
+ * "usb2_quirk.h".
+ */
+ char quirkname[64 - 14];
+};
+
/* USB controller */
#define USB_REQUEST _IOWR('U', 1, struct usb2_ctl_request)
#define USB_SETDEBUG _IOW ('U', 2, int)
@@ -278,4 +292,10 @@
#define USB_FS_CLOSE _IOW ('U', 198, struct usb2_fs_close)
#define USB_FS_CLEAR_STALL_SYNC _IOW ('U', 199, struct usb2_fs_clear_stall_sync)
+/* USB quirk system interface */
+#define USB_DEV_QUIRK_GET _IOWR('Q', 0, struct usb2_gen_quirk)
+#define USB_QUIRK_NAME_GET _IOWR('Q', 1, struct usb2_gen_quirk)
+#define USB_DEV_QUIRK_ADD _IOW ('Q', 2, struct usb2_gen_quirk)
+#define USB_DEV_QUIRK_REMOVE _IOW ('Q', 3, struct usb2_gen_quirk)
+
#endif /* _USB2_IOCTL_H_ */
==== //depot/projects/usb/src/sys/dev/usb2/quirk/usb2_quirk.c#7 (text+ko) ====
@@ -26,6 +26,8 @@
* SUCH DAMAGE.
*/
+#include <dev/usb2/include/usb2_standard.h>
+#include <dev/usb2/include/usb2_ioctl.h>
#include <dev/usb2/include/usb2_mfunc.h>
#include <dev/usb2/include/usb2_devid.h>
@@ -42,68 +44,70 @@
MODULE_VERSION(usb2_quirk, 1);
/*
- * The following macro adds a quirk for any revision of a device:
+ * The following macro adds one or more quirks for a USB device:
*/
-#define USB_VPA(v,p,r,...) \
- USB_VPI(v,p,((const uint16_t []){__VA_ARGS__}))
+#define USB_QUIRK_ENTRY(v,p,l,h,...) \
+ .vid = (v), .pid = (p), .lo_rev = (l), .hi_rev = (h), .quirks = { __VA_ARGS__ }
+
+#define USB_DEV_QUIRKS_MAX 128
+#define USB_SUB_QUIRKS_MAX 8
+
+struct usb2_quirk_entry {
+ uint16_t vid;
+ uint16_t pid;
+ uint16_t lo_rev;
+ uint16_t hi_rev;
+ uint16_t quirks[USB_SUB_QUIRKS_MAX];
+};
-/*
- * The following macro adds a quirk for a specific revision of a
- * device:
- */
-#define USB_VPR(v,p,r,...) \
- USB_VPI(v,p, ((const uint16_t []){__VA_ARGS__})), \
- USB_DEV_BCD_LTEQ(r), \
- USB_DEV_BCD_GTEQ(r)
+static struct mtx usb2_quirk_mtx;
-/* try to keep the quirks on one line, hence grepping becomes easier */
+static struct usb2_quirk_entry usb2_quirks[USB_DEV_QUIRKS_MAX] = {
+ {USB_QUIRK_ENTRY(USB_VENDOR_ASUS, USB_PRODUCT_ASUS_LCM, 0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_INSIDEOUT, USB_PRODUCT_INSIDEOUT_EDGEPORT4, 0x094, 0x094, UQ_SWAP_UNICODE, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502, 0x0a2, 0x0a2, UQ_BAD_ADC, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502, 0x0a2, 0x0a2, UQ_AU_NO_XU, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ADA70, 0x103, 0x103, UQ_BAD_ADC, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ASC495, 0x000, 0x000, UQ_BAD_AUDIO, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_QTRONIX, USB_PRODUCT_QTRONIX_980N, 0x110, 0x110, UQ_SPUR_BUT_UP, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_ALCOR2, USB_PRODUCT_ALCOR2_KBD_HUB, 0x001, 0x001, UQ_SPUR_BUT_UP, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_MCT, USB_PRODUCT_MCT_HUB0100, 0x102, 0x102, UQ_BUS_POWERED, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_MCT, USB_PRODUCT_MCT_USB232, 0x102, 0x102, UQ_BUS_POWERED, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_TI, USB_PRODUCT_TI_UTUSB41, 0x110, 0x110, UQ_POWER_CLAIM, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_TELEX, USB_PRODUCT_TELEX_MIC1, 0x009, 0x009, UQ_AU_NO_FRAC, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_SILICONPORTALS, USB_PRODUCT_SILICONPORTALS_YAPPHONE, 0x100, 0x100, UQ_AU_INP_ASYNC, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_UN53B, 0x0000, 0xFFFF, UQ_NO_STRINGS, UQ_NONE)},
-static const struct usb2_device_id usb2_quirks[] = {
- {USB_VPA(USB_VENDOR_ASUS, USB_PRODUCT_ASUS_LCM, 0x000, UQ_HID_IGNORE, UQ_NONE)},
- {USB_VPR(USB_VENDOR_INSIDEOUT, USB_PRODUCT_INSIDEOUT_EDGEPORT4, 0x094, UQ_SWAP_UNICODE, UQ_NONE)},
- {USB_VPR(USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502, 0x0a2, UQ_BAD_ADC, UQ_NONE)},
- {USB_VPR(USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502, 0x0a2, UQ_AU_NO_XU, UQ_NONE)},
- {USB_VPR(USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ADA70, 0x103, UQ_BAD_ADC, UQ_NONE)},
- {USB_VPR(USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ASC495, 0x000, UQ_BAD_AUDIO, UQ_NONE)},
- {USB_VPR(USB_VENDOR_QTRONIX, USB_PRODUCT_QTRONIX_980N, 0x110, UQ_SPUR_BUT_UP, UQ_NONE)},
- {USB_VPR(USB_VENDOR_ALCOR2, USB_PRODUCT_ALCOR2_KBD_HUB, 0x001, UQ_SPUR_BUT_UP, UQ_NONE)},
- {USB_VPR(USB_VENDOR_MCT, USB_PRODUCT_MCT_HUB0100, 0x102, UQ_BUS_POWERED, UQ_NONE)},
- {USB_VPR(USB_VENDOR_MCT, USB_PRODUCT_MCT_USB232, 0x102, UQ_BUS_POWERED, UQ_NONE)},
- {USB_VPR(USB_VENDOR_TI, USB_PRODUCT_TI_UTUSB41, 0x110, UQ_POWER_CLAIM, UQ_NONE)},
- {USB_VPR(USB_VENDOR_TELEX, USB_PRODUCT_TELEX_MIC1, 0x009, UQ_AU_NO_FRAC, UQ_NONE)},
- {USB_VPR(USB_VENDOR_SILICONPORTALS, USB_PRODUCT_SILICONPORTALS_YAPPHONE, 0x100, UQ_AU_INP_ASYNC, UQ_NONE)},
- {USB_VPA(USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_UN53B, 0x000, UQ_NO_STRINGS, UQ_NONE)},
/*
- * XXX These should have a revision number, but I don't know what
- * they are.
+ * XXX The following quirks should have a more specific revision
+ * number:
*/
- {USB_VPA(USB_VENDOR_HP, USB_PRODUCT_HP_895C, 0x000, UQ_BROKEN_BIDIR, UQ_NONE)},
- {USB_VPA(USB_VENDOR_HP, USB_PRODUCT_HP_880C, 0x000, UQ_BROKEN_BIDIR, UQ_NONE)},
- {USB_VPA(USB_VENDOR_HP, USB_PRODUCT_HP_815C, 0x000, UQ_BROKEN_BIDIR, UQ_NONE)},
- {USB_VPA(USB_VENDOR_HP, USB_PRODUCT_HP_810C, 0x000, UQ_BROKEN_BIDIR, UQ_NONE)},
- {USB_VPA(USB_VENDOR_HP, USB_PRODUCT_HP_830C, 0x000, UQ_BROKEN_BIDIR, UQ_NONE)},
- {USB_VPA(USB_VENDOR_HP, USB_PRODUCT_HP_1220C, 0x000, UQ_BROKEN_BIDIR, UQ_NONE)},
- {USB_VPA(USB_VENDOR_XEROX, USB_PRODUCT_XEROX_WCM15, 0x000, UQ_BROKEN_BIDIR, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_HP, USB_PRODUCT_HP_895C, 0x0000, 0xFFFF, UQ_BROKEN_BIDIR, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_HP, USB_PRODUCT_HP_880C, 0x0000, 0xFFFF, UQ_BROKEN_BIDIR, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_HP, USB_PRODUCT_HP_815C, 0x0000, 0xFFFF, UQ_BROKEN_BIDIR, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_HP, USB_PRODUCT_HP_810C, 0x0000, 0xFFFF, UQ_BROKEN_BIDIR, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_HP, USB_PRODUCT_HP_830C, 0x0000, 0xFFFF, UQ_BROKEN_BIDIR, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_HP, USB_PRODUCT_HP_1220C, 0x0000, 0xFFFF, UQ_BROKEN_BIDIR, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_XEROX, USB_PRODUCT_XEROX_WCM15, 0x0000, 0xFFFF, UQ_BROKEN_BIDIR, UQ_NONE)},
/* Devices which should be ignored by uhid */
- {USB_VPA(USB_VENDOR_APC, USB_PRODUCT_APC_UPS, 0x000, UQ_HID_IGNORE, UQ_NONE)},
- {USB_VPA(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F6C550AVR, 0x000, UQ_HID_IGNORE, UQ_NONE)},
- {USB_VPA(USB_VENDOR_CYBERPOWER, USB_PRODUCT_CYBERPOWER_1500CAVRLCD, 0x000, UQ_HID_IGNORE, UQ_NONE)},
- {USB_VPA(USB_VENDOR_DELORME, USB_PRODUCT_DELORME_EARTHMATE, 0x000, UQ_HID_IGNORE, UQ_NONE)},
- {USB_VPA(USB_VENDOR_ITUNERNET, USB_PRODUCT_ITUNERNET_USBLCD2X20, 0x000, UQ_HID_IGNORE, UQ_NONE)},
- {USB_VPA(USB_VENDOR_MGE, USB_PRODUCT_MGE_UPS1, 0x000, UQ_HID_IGNORE, UQ_NONE)},
- {USB_VPA(USB_VENDOR_MGE, USB_PRODUCT_MGE_UPS2, 0x000, UQ_HID_IGNORE, UQ_NONE)},
- {USB_VPA(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE, 0x000, UQ_HID_IGNORE, UQ_NONE)},
- {USB_VPA(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3G, 0x000, UQ_HID_IGNORE, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_APC, USB_PRODUCT_APC_UPS, 0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F6C550AVR, 0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_CYBERPOWER, USB_PRODUCT_CYBERPOWER_1500CAVRLCD, 0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_DELORME, USB_PRODUCT_DELORME_EARTHMATE, 0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_ITUNERNET, USB_PRODUCT_ITUNERNET_USBLCD2X20, 0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_MGE, USB_PRODUCT_MGE_UPS1, 0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_MGE, USB_PRODUCT_MGE_UPS2, 0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE, 0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3G, 0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
/* Devices which should be ignored by both ukbd and uhid */
- {USB_VPA(USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_WISPY1A, 0x000, UQ_KBD_IGNORE, UQ_HID_IGNORE, UQ_NONE)},
- {USB_VPA(USB_VENDOR_METAGEEK, USB_PRODUCT_METAGEEK_WISPY1B, 0x000, UQ_KBD_IGNORE, UQ_HID_IGNORE, UQ_NONE)},
- {USB_VPR(USB_VENDOR_TENX, USB_PRODUCT_TENX_UAUDIO0, 0x0101, UQ_AUDIO_SWAP_LR, UQ_NONE)},
-
+ {USB_QUIRK_ENTRY(USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_WISPY1A, 0x0000, 0xFFFF, UQ_KBD_IGNORE, UQ_HID_IGNORE, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_METAGEEK, USB_PRODUCT_METAGEEK_WISPY1B, 0x0000, 0xFFFF, UQ_KBD_IGNORE, UQ_HID_IGNORE, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_TENX, USB_PRODUCT_TENX_UAUDIO0, 0x0101, 0x0101, UQ_AUDIO_SWAP_LR, UQ_NONE)},
/* MS keyboards do weird things */
- {USB_VPA(USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_WLNOTEBOOK, 0x000, UQ_MS_BAD_CLASS, UQ_MS_LEADING_BYTE, UQ_NONE)},
- {USB_VPA(USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_WLNOTEBOOK2, 0x000, UQ_MS_BAD_CLASS, UQ_MS_LEADING_BYTE, UQ_NONE)},
- {USB_VPA(USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_WLINTELLIMOUSE, 0x000, UQ_MS_LEADING_BYTE, UQ_NONE)},
- {USB_VPA(USB_VENDOR_METAGEEK, USB_PRODUCT_METAGEEK_WISPY24X, 0x000, UQ_KBD_IGNORE, UQ_HID_IGNORE, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_WLNOTEBOOK, 0x0000, 0xFFFF, UQ_MS_BAD_CLASS, UQ_MS_LEADING_BYTE, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_WLNOTEBOOK2, 0x0000, 0xFFFF, UQ_MS_BAD_CLASS, UQ_MS_LEADING_BYTE, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_WLINTELLIMOUSE, 0x0000, 0xFFFF, UQ_MS_LEADING_BYTE, UQ_NONE)},
+ {USB_QUIRK_ENTRY(USB_VENDOR_METAGEEK, USB_PRODUCT_METAGEEK_WISPY24X, 0x0000, 0xFFFF, UQ_KBD_IGNORE, UQ_HID_IGNORE, UQ_NONE)},
};
USB_MAKE_DEBUG_TABLE(USB_QUIRK);
@@ -130,36 +134,239 @@
static uint8_t
usb2_test_quirk_by_info(const struct usb2_lookup_info *info, uint16_t quirk)
{
- const struct usb2_device_id *pe;
- const uint16_t *px;
+ uint16_t x;
+ uint16_t y;
if (quirk == UQ_NONE) {
return (0);
}
- pe = usb2_lookup_id_by_info(usb2_quirks, sizeof(usb2_quirks), info);
- if (pe && pe->driver_info) {
- px = pe->driver_info;
- while (1) {
- if (*px == quirk) {
+ mtx_lock(&usb2_quirk_mtx);
+
+ for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) {
+ /* see if quirk information does not match */
+ if ((usb2_quirks[x].vid != info->idVendor) ||
+ (usb2_quirks[x].pid != info->idProduct) ||
+ (usb2_quirks[x].lo_rev > info->bcdDevice) ||
+ (usb2_quirks[x].hi_rev < info->bcdDevice)) {
+ continue;
+ }
+ /* lookup quirk */
+ for (y = 0; y != USB_SUB_QUIRKS_MAX; y++) {
+ if (usb2_quirks[x].quirks[y] == quirk) {
+ mtx_unlock(&usb2_quirk_mtx);
DPRINTF("Found quirk '%s'.\n", usb2_quirkstr(quirk));
return (1);
}
- if (*px == UQ_NONE) {
- return (0);
+ }
+ /* no quirk found */
+ break;
+ }
+ mtx_unlock(&usb2_quirk_mtx);
+ return (0);
+}
+
+static struct usb2_quirk_entry *
+usb2_quirk_get_entry(uint16_t vid, uint16_t pid,
+ uint16_t lo_rev, uint16_t hi_rev, uint8_t do_alloc)
+{
+ uint16_t x;
+
+ mtx_assert(&usb2_quirk_mtx, MA_OWNED);
+
+ if ((vid | pid | lo_rev | hi_rev) == 0) {
+ /* all zero - special case */
+ return (usb2_quirks + USB_DEV_QUIRKS_MAX - 1);
+ }
+ /* search for an existing entry */
+ for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) {
+ /* see if quirk information does not match */
+ if ((usb2_quirks[x].vid != vid) ||
+ (usb2_quirks[x].pid != pid) ||
+ (usb2_quirks[x].lo_rev != lo_rev) ||
+ (usb2_quirks[x].hi_rev != hi_rev)) {
+ continue;
+ }
+ return (usb2_quirks + x);
+ }
+
+ if (do_alloc == 0) {
+ /* no match */
+ return (NULL);
+ }
+ /* search for a free entry */
+ for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) {
+ /* see if quirk information does not match */
+ if ((usb2_quirks[x].vid |
+ usb2_quirks[x].pid |
+ usb2_quirks[x].lo_rev |
+ usb2_quirks[x].hi_rev) != 0) {
+ continue;
+ }
+ usb2_quirks[x].vid = vid;
+ usb2_quirks[x].pid = pid;
+ usb2_quirks[x].lo_rev = lo_rev;
+ usb2_quirks[x].hi_rev = hi_rev;
+
+ return (usb2_quirks + x);
+ }
+
+ /* no entry found */
+ return (NULL);
+}
+
+/*------------------------------------------------------------------------*
+ * usb2_quirk_ioctl - handle quirk IOCTLs
+ *
+ * Returns:
+ * 0: Success
+ * Else: Failure
+ *------------------------------------------------------------------------*/
+static int
+usb2_quirk_ioctl(unsigned long cmd, caddr_t data,
+ int fflag, struct thread *td)
+{
+ struct usb2_gen_quirk *pgq;
+ struct usb2_quirk_entry *pqe;
+ uint32_t x;
+ uint32_t y;
+ int err;
+
+ switch (cmd) {
+ case USB_DEV_QUIRK_GET:
+ pgq = (void *)data;
+ x = pgq->index % USB_SUB_QUIRKS_MAX;
+ y = pgq->index / USB_SUB_QUIRKS_MAX;
+ if (y >= USB_DEV_QUIRKS_MAX) {
+ return (EINVAL);
+ }
+ mtx_lock(&usb2_quirk_mtx);
+ /* copy out data */
+ pgq->vid = usb2_quirks[y].vid;
+ pgq->pid = usb2_quirks[y].pid;
+ pgq->bcdDeviceLow = usb2_quirks[y].lo_rev;
+ pgq->bcdDeviceHigh = usb2_quirks[y].hi_rev;
+ strlcpy(pgq->quirkname,
+ usb2_quirkstr(usb2_quirks[y].quirks[x]),
+ sizeof(pgq->quirkname));
+ mtx_unlock(&usb2_quirk_mtx);
+ return (0); /* success */
+
+ case USB_QUIRK_NAME_GET:
+ pgq = (void *)data;
+ x = pgq->index;
+ if (x >= USB_QUIRK_MAX) {
+ return (EINVAL);
+ }
+ strlcpy(pgq->quirkname,
+ usb2_quirkstr(x), sizeof(pgq->quirkname));
+ return (0); /* success */
+
+ case USB_DEV_QUIRK_ADD:
+ pgq = (void *)data;
+
+ /* check privileges */
+ err = priv_check(curthread, PRIV_DRIVER);
+ if (err) {
+ return (err);
+ }
+ /* convert quirk string into numerical */
+ for (y = 0; y != USB_DEV_QUIRKS_MAX; y++) {
+ if (strcmp(pgq->quirkname, usb2_quirkstr(y)) == 0) {
+ break;
+ }
+ }
+ if (y == USB_DEV_QUIRKS_MAX) {
+ return (EINVAL);
+ }
+ if (y == UQ_NONE) {
+ return (EINVAL);
+ }
+ mtx_lock(&usb2_quirk_mtx);
+ pqe = usb2_quirk_get_entry(pgq->vid, pgq->pid,
+ pgq->bcdDeviceLow, pgq->bcdDeviceHigh, 1);
+ for (x = 0; x != USB_SUB_QUIRKS_MAX; x++) {
+ if (pqe->quirks[x] == UQ_NONE) {
+ pqe->quirks[x] = y;
+ break;
+ }
+ }
+ mtx_unlock(&usb2_quirk_mtx);
+ if (x == USB_SUB_QUIRKS_MAX) {
+ return (ENOMEM);
+ }
+ return (0); /* success */
+
+ case USB_DEV_QUIRK_REMOVE:
+ pgq = (void *)data;
+ /* check privileges */
+ err = priv_check(curthread, PRIV_DRIVER);
+ if (err) {
+ return (err);
+ }
+ /* convert quirk string into numerical */
+ for (y = 0; y != USB_DEV_QUIRKS_MAX; y++) {
+ if (strcmp(pgq->quirkname, usb2_quirkstr(y)) == 0) {
+ break;
+ }
+ }
+ if (y == USB_DEV_QUIRKS_MAX) {
+ return (EINVAL);
+ }
+ if (y == UQ_NONE) {
+ return (EINVAL);
+ }
+ mtx_lock(&usb2_quirk_mtx);
+ pqe = usb2_quirk_get_entry(pgq->vid, pgq->pid,
+ pgq->bcdDeviceLow, pgq->bcdDeviceHigh, 0);
+ for (x = 0; x != USB_SUB_QUIRKS_MAX; x++) {
+ if (pqe->quirks[x] == y) {
+ pqe->quirks[x] = UQ_NONE;
+ break;
+ }
+ }
+ if (x == USB_SUB_QUIRKS_MAX) {
+ mtx_unlock(&usb2_quirk_mtx);
+ return (ENOMEM);
+ }
+ for (x = 0; x != USB_SUB_QUIRKS_MAX; x++) {
+ if (pqe->quirks[x] != UQ_NONE) {
+ break;
}
- px++;
+ }
+ if (x == USB_SUB_QUIRKS_MAX) {
+ /* all quirk entries are unused - release */
+ memset(pqe, 0, sizeof(pqe));
}
+ mtx_unlock(&usb2_quirk_mtx);
+ return (0); /* success */
+
+ default:
+ break;
}
- return (0);
+ return (ENOIOCTL);
}
static void
usb2_quirk_init(void *arg)
{
+ /* initialize mutex */
+ mtx_init(&usb2_quirk_mtx, "USB quirk", NULL, MTX_DEF);
+
/* register our function */
usb2_test_quirk_p = &usb2_test_quirk_by_info;
+ usb2_quirk_ioctl_p = &usb2_quirk_ioctl;
return;
}
+static void
+usb2_quirk_uninit(void *arg)
+{
+ usb2_quirk_unload(arg);
+
+ /* destroy mutex */
+ mtx_destroy(&usb2_quirk_mtx);
+ return;
+}
+
SYSINIT(usb2_quirk_init, SI_SUB_LOCK, SI_ORDER_FIRST, usb2_quirk_init, NULL);
-SYSUNINIT(usb2_quirk_unload, SI_SUB_LOCK, SI_ORDER_ANY, usb2_quirk_unload, NULL);
+SYSUNINIT(usb2_quirk_uninit, SI_SUB_LOCK, SI_ORDER_ANY, usb2_quirk_uninit, NULL);
==== //depot/projects/usb/src/usr.sbin/usbconfig/dump.c#6 (text+ko) ====
@@ -260,7 +260,8 @@
}
break;
}
- printf("%s\n", q.quirkname);
+ if (strcmp(q.quirkname, "UQ_NONE"))
+ printf("%s\n", q.quirkname);
}
printf("\n");
return;
@@ -280,17 +281,19 @@
for (x = 0; x != 0xFFFF; x++) {
err = libusb20_be_get_dev_quirk(pbe, x, &q);
- if (err == LIBUSB20_ERROR_NOT_FOUND) {
- continue;
- } else if (err) {
+ if (err) {
if (x == 0) {
printf("No device quirks - maybe the USB quirk "
"module has not been loaded.\n");
}
break;
}
- printf("VID=0x%04x PID=0x%04x QUIRK=%s\n",
- q.vid, q.pid, q.quirkname);
+ if (strcmp(q.quirkname, "UQ_NONE")) {
+ printf("VID=0x%04x PID=0x%04x REVLO=0x%04x "
+ "REVHI=0x%04x QUIRK=%s\n",
+ q.vid, q.pid, q.bcdDeviceLow,
+ q.bcdDeviceHigh, q.quirkname);
+ }
}
printf("\n");
return;
==== //depot/projects/usb/src/usr.sbin/usbconfig/usbconfig.c#3 (text+ko) ====
@@ -49,6 +49,8 @@
uint16_t iface;
uint16_t vid;
uint16_t pid;
+ uint16_t lo_rev; /* inclusive */
+ uint16_t hi_rev; /* inclusive */
uint8_t config_index;
uint8_t alt_index;
uint8_t got_list:1;
@@ -118,8 +120,8 @@
{"set_alt", T_SET_ALT, 1},
{"set_owner", T_SET_OWNER, 1},
{"set_perm", T_SET_PERM, 1},
- {"add_dev_quirk", T_ADD_DEVICE_QUIRK, 3},
- {"remove_dev_quirk", T_REMOVE_DEVICE_QUIRK, 3},
+ {"add_dev_quirk_vplh", T_ADD_DEVICE_QUIRK, 5},
+ {"remove_dev_quirk_vplh", T_REMOVE_DEVICE_QUIRK, 5},
{"dump_quirk_names", T_DUMP_QUIRK_NAMES, 0},
{"dump_device_quirks", T_DUMP_DEVICE_QUIRKS, 0},
{"dump_device_desc", T_DUMP_DEVICE_DESC, 0},
@@ -137,7 +139,9 @@
};
static void
-be_dev_remove_quirk(struct libusb20_backend *pbe, uint16_t vid, uint16_t pid, const char *str)
+be_dev_remove_quirk(struct libusb20_backend *pbe,
+ uint16_t vid, uint16_t pid, uint16_t lorev, uint16_t hirev,
+ const char *str)
{
struct libusb20_quirk q;
int err;
@@ -146,6 +150,8 @@
q.vid = vid;
q.pid = pid;
+ q.bcdDeviceLow = lorev;
+ q.bcdDeviceHigh = hirev;
strlcpy(q.quirkname, str, sizeof(q.quirkname));
err = libusb20_be_remove_dev_quirk(pbe, &q);
@@ -156,7 +162,9 @@
}
static void
-be_dev_add_quirk(struct libusb20_backend *pbe, uint16_t vid, uint16_t pid, const char *str)
+be_dev_add_quirk(struct libusb20_backend *pbe,
+ uint16_t vid, uint16_t pid, uint16_t lorev, uint16_t hirev,
+ const char *str)
{
struct libusb20_quirk q;
int err;
@@ -165,6 +173,8 @@
q.vid = vid;
q.pid = pid;
+ q.bcdDeviceLow = lorev;
+ q.bcdDeviceHigh = hirev;
strlcpy(q.quirkname, str, sizeof(q.quirkname));
err = libusb20_be_add_dev_quirk(pbe, &q);
@@ -260,8 +270,8 @@
" set_alt <altno>" "\n"
" set_owner <user:group>" "\n"
" set_perm <mode>" "\n"
- " add_dev_quirk <vid> <pid> <quirk>" "\n"
- " remove_dev_quirk <vid> <pid> <quirk>" "\n"
+ " add_dev_quirk_vplh <vid> <pid> <lo_rev> <hi_rev> <quirk>" "\n"
+ " remove_dev_quirk_vplh <vid> <pid> <lo_rev> <hi_rev> <quirk>" "\n"
" dump_quirk_names" "\n"
" dump_device_quirks" "\n"
" dump_device_desc" "\n"
@@ -322,11 +332,13 @@
}
if (opt->got_remove_device_quirk) {
opt->got_any--;
- be_dev_remove_quirk(pbe, opt->vid, opt->pid, opt->quirkname);
+ be_dev_remove_quirk(pbe,
+ opt->vid, opt->pid, opt->lo_rev, opt->hi_rev, opt->quirkname);
}
if (opt->got_add_device_quirk) {
opt->got_any--;
- be_dev_add_quirk(pbe, opt->vid, opt->pid, opt->quirkname);
+ be_dev_add_quirk(pbe,
+ opt->vid, opt->pid, opt->lo_rev, opt->hi_rev, opt->quirkname);
}
if (opt->got_any == 0) {
/*
@@ -519,8 +531,10 @@
}
opt->vid = num_id(argv[n + 1], "Vendor ID");
opt->pid = num_id(argv[n + 2], "Product ID");
- opt->quirkname = argv[n + 3];
- n += 3;
+ opt->lo_rev = num_id(argv[n + 3], "Low Revision");
+ opt->hi_rev = num_id(argv[n + 4], "High Revision");
+ opt->quirkname = argv[n + 5];
+ n += 5;
opt->got_add_device_quirk = 1;
opt->got_any++;
@@ -532,9 +546,10 @@
}
opt->vid = num_id(argv[n + 1], "Vendor ID");
opt->pid = num_id(argv[n + 2], "Product ID");
- opt->quirkname = argv[n + 3];
- n += 3;
-
+ opt->lo_rev = num_id(argv[n + 3], "Low Revision");
+ opt->hi_rev = num_id(argv[n + 4], "High Revision");
+ opt->quirkname = argv[n + 5];
+ n += 5;
opt->got_remove_device_quirk = 1;
opt->got_any++;
break;
More information about the p4-projects
mailing list