Date: Sun, 26 Oct 2008 13:28:33 GMT From: Hans Petter Selasky <hselasky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 151947 for review Message-ID: <200810261328.m9QDSXr9063836@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=151947 Change 151947 by hselasky@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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200810261328.m9QDSXr9063836>