Fix detection of Razer Copperhead as a USB mouse.
Factor out USB mouse and keyboard detection logic. Reject USB keyboards which have mouse alike HID items in their HID descriptors. Submitted by: Matthew W MFC after: 1 week
This commit is contained in:
parent
0bad7195e9
commit
be9f533741
@ -995,13 +995,12 @@ ukbd_probe(device_t dev)
|
||||
if (uaa->info.bInterfaceClass != UICLASS_HID)
|
||||
return (ENXIO);
|
||||
|
||||
if (usb_test_quirk(uaa, UQ_KBD_IGNORE))
|
||||
return (ENXIO);
|
||||
|
||||
if ((uaa->info.bInterfaceSubClass == UISUBCLASS_BOOT) &&
|
||||
(uaa->info.bInterfaceProtocol == UIPROTO_BOOT_KEYBOARD)) {
|
||||
if (usb_test_quirk(uaa, UQ_KBD_IGNORE))
|
||||
return (ENXIO);
|
||||
else
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
(uaa->info.bInterfaceProtocol == UIPROTO_BOOT_KEYBOARD))
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
|
||||
error = usbd_req_get_hid_desc(uaa->device, NULL,
|
||||
&d_ptr, &d_len, M_TEMP, uaa->info.bIfaceIndex);
|
||||
@ -1009,23 +1008,20 @@ ukbd_probe(device_t dev)
|
||||
if (error)
|
||||
return (ENXIO);
|
||||
|
||||
/*
|
||||
* NOTE: we currently don't support USB mouse and USB keyboard
|
||||
* on the same USB endpoint.
|
||||
*/
|
||||
if (hid_is_collection(d_ptr, d_len,
|
||||
HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))) {
|
||||
/* most likely a mouse */
|
||||
error = ENXIO;
|
||||
} else if (hid_is_collection(d_ptr, d_len,
|
||||
HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD))) {
|
||||
if (usb_test_quirk(uaa, UQ_KBD_IGNORE))
|
||||
if (hid_is_keyboard(d_ptr, d_len)) {
|
||||
if (hid_is_mouse(d_ptr, d_len)) {
|
||||
/*
|
||||
* NOTE: We currently don't support USB mouse
|
||||
* and USB keyboard on the same USB endpoint.
|
||||
* Let "ums" driver win.
|
||||
*/
|
||||
error = ENXIO;
|
||||
else
|
||||
} else {
|
||||
error = BUS_PROBE_DEFAULT;
|
||||
} else
|
||||
}
|
||||
} else {
|
||||
error = ENXIO;
|
||||
|
||||
}
|
||||
free(d_ptr, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
|
@ -368,9 +368,7 @@ ums_probe(device_t dev)
|
||||
{
|
||||
struct usb_attach_arg *uaa = device_get_ivars(dev);
|
||||
void *d_ptr;
|
||||
struct hid_data *hd;
|
||||
struct hid_item hi;
|
||||
int error, mdepth, found;
|
||||
int error;
|
||||
uint16_t d_len;
|
||||
|
||||
DPRINTFN(11, "\n");
|
||||
@ -394,44 +392,13 @@ ums_probe(device_t dev)
|
||||
if (error)
|
||||
return (ENXIO);
|
||||
|
||||
hd = hid_start_parse(d_ptr, d_len, 1 << hid_input);
|
||||
if (hd == NULL)
|
||||
return (0);
|
||||
mdepth = 0;
|
||||
found = 0;
|
||||
while (hid_get_item(hd, &hi)) {
|
||||
switch (hi.kind) {
|
||||
case hid_collection:
|
||||
if (mdepth != 0)
|
||||
mdepth++;
|
||||
else if (hi.collection == 1 &&
|
||||
hi.usage ==
|
||||
HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))
|
||||
mdepth++;
|
||||
break;
|
||||
case hid_endcollection:
|
||||
if (mdepth != 0)
|
||||
mdepth--;
|
||||
break;
|
||||
case hid_input:
|
||||
if (mdepth == 0)
|
||||
break;
|
||||
if (hi.usage ==
|
||||
HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X) &&
|
||||
(hi.flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS)
|
||||
found++;
|
||||
if (hi.usage ==
|
||||
HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y) &&
|
||||
(hi.flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS)
|
||||
found++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
hid_end_parse(hd);
|
||||
if (hid_is_mouse(d_ptr, d_len))
|
||||
error = BUS_PROBE_DEFAULT;
|
||||
else
|
||||
error = ENXIO;
|
||||
|
||||
free(d_ptr, M_TEMP);
|
||||
return (found ? BUS_PROBE_DEFAULT : ENXIO);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -845,3 +845,79 @@ usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx,
|
||||
}
|
||||
return (USB_ERR_NORMAL_COMPLETION);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* hid_is_mouse
|
||||
*
|
||||
* This function will decide if a USB descriptor belongs to a USB mouse.
|
||||
*
|
||||
* Return values:
|
||||
* Zero: Not a USB mouse.
|
||||
* Else: Is a USB mouse.
|
||||
*------------------------------------------------------------------------*/
|
||||
int
|
||||
hid_is_mouse(const void *d_ptr, uint16_t d_len)
|
||||
{
|
||||
struct hid_data *hd;
|
||||
struct hid_item hi;
|
||||
int mdepth;
|
||||
int found;
|
||||
|
||||
hd = hid_start_parse(d_ptr, d_len, 1 << hid_input);
|
||||
if (hd == NULL)
|
||||
return (0);
|
||||
|
||||
mdepth = 0;
|
||||
found = 0;
|
||||
|
||||
while (hid_get_item(hd, &hi)) {
|
||||
switch (hi.kind) {
|
||||
case hid_collection:
|
||||
if (mdepth != 0)
|
||||
mdepth++;
|
||||
else if (hi.collection == 1 &&
|
||||
hi.usage ==
|
||||
HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))
|
||||
mdepth++;
|
||||
break;
|
||||
case hid_endcollection:
|
||||
if (mdepth != 0)
|
||||
mdepth--;
|
||||
break;
|
||||
case hid_input:
|
||||
if (mdepth == 0)
|
||||
break;
|
||||
if (hi.usage ==
|
||||
HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X) &&
|
||||
(hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE)
|
||||
found++;
|
||||
if (hi.usage ==
|
||||
HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y) &&
|
||||
(hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE)
|
||||
found++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
hid_end_parse(hd);
|
||||
return (found);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* hid_is_keyboard
|
||||
*
|
||||
* This function will decide if a USB descriptor belongs to a USB keyboard.
|
||||
*
|
||||
* Return values:
|
||||
* Zero: Not a USB keyboard.
|
||||
* Else: Is a USB keyboard.
|
||||
*------------------------------------------------------------------------*/
|
||||
int
|
||||
hid_is_keyboard(const void *d_ptr, uint16_t d_len)
|
||||
{
|
||||
if (hid_is_collection(d_ptr, d_len,
|
||||
HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD)))
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
@ -242,5 +242,7 @@ struct usb_hid_descriptor *hid_get_descriptor_from_usb(
|
||||
usb_error_t usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx,
|
||||
void **descp, uint16_t *sizep, struct malloc_type *mem,
|
||||
uint8_t iface_index);
|
||||
int hid_is_mouse(const void *d_ptr, uint16_t d_len);
|
||||
int hid_is_keyboard(const void *d_ptr, uint16_t d_len);
|
||||
#endif /* _KERNEL */
|
||||
#endif /* _USB_HID_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user