mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-18 10:35:55 +00:00
USB CORE:
- Add minimum polling support to drive UMASS and UKBD in case of panic. - Add extra check to ukbd probe to fix problem about mouse devices attaching like keyboards. - P4 ID: 166148 Submitted by: hps Approved by: re
This commit is contained in:
parent
81f8288460
commit
dddb25f98a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=195960
@ -2326,4 +2326,5 @@ struct usb_bus_methods at91dci_bus_methods =
|
||||
.set_stall = &at91dci_set_stall,
|
||||
.clear_stall = &at91dci_clear_stall,
|
||||
.roothub_exec = &at91dci_roothub_exec,
|
||||
.xfer_poll = &at91dci_do_poll,
|
||||
};
|
||||
|
@ -2143,4 +2143,5 @@ struct usb_bus_methods atmegadci_bus_methods =
|
||||
.set_stall = &atmegadci_set_stall,
|
||||
.clear_stall = &atmegadci_clear_stall,
|
||||
.roothub_exec = &atmegadci_roothub_exec,
|
||||
.xfer_poll = &atmegadci_do_poll,
|
||||
};
|
||||
|
@ -2081,4 +2081,5 @@ struct usb_bus_methods avr32dci_bus_methods =
|
||||
.set_stall = &avr32dci_set_stall,
|
||||
.clear_stall = &avr32dci_clear_stall,
|
||||
.roothub_exec = &avr32dci_roothub_exec,
|
||||
.xfer_poll = &avr32dci_do_poll,
|
||||
};
|
||||
|
@ -3828,4 +3828,5 @@ struct usb_bus_methods ehci_bus_methods =
|
||||
.device_suspend = ehci_device_suspend,
|
||||
.set_hw_power = ehci_set_hw_power,
|
||||
.roothub_exec = ehci_roothub_exec,
|
||||
.xfer_poll = ehci_do_poll,
|
||||
};
|
||||
|
@ -2736,4 +2736,5 @@ struct usb_bus_methods musbotg_bus_methods =
|
||||
.set_stall = &musbotg_set_stall,
|
||||
.clear_stall = &musbotg_clear_stall,
|
||||
.roothub_exec = &musbotg_roothub_exec,
|
||||
.xfer_poll = &musbotg_do_poll,
|
||||
};
|
||||
|
@ -2756,4 +2756,5 @@ struct usb_bus_methods ohci_bus_methods =
|
||||
.device_suspend = ohci_device_suspend,
|
||||
.set_hw_power = ohci_set_hw_power,
|
||||
.roothub_exec = ohci_roothub_exec,
|
||||
.xfer_poll = ohci_do_poll,
|
||||
};
|
||||
|
@ -3251,4 +3251,5 @@ struct usb_bus_methods uhci_bus_methods =
|
||||
.device_suspend = uhci_device_suspend,
|
||||
.set_hw_power = uhci_set_hw_power,
|
||||
.roothub_exec = uhci_roothub_exec,
|
||||
.xfer_poll = uhci_do_poll,
|
||||
};
|
||||
|
@ -2360,4 +2360,5 @@ struct usb_bus_methods uss820dci_bus_methods =
|
||||
.set_stall = &uss820dci_set_stall,
|
||||
.clear_stall = &uss820dci_clear_stall,
|
||||
.roothub_exec = &uss820dci_roothub_exec,
|
||||
.xfer_poll = &uss820dci_do_poll,
|
||||
};
|
||||
|
@ -299,6 +299,28 @@ ukbd_put_key(struct ukbd_softc *sc, uint32_t key)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ukbd_do_poll(struct ukbd_softc *sc, uint8_t wait)
|
||||
{
|
||||
DPRINTFN(2, "polling\n");
|
||||
|
||||
while (sc->sc_inputs == 0) {
|
||||
|
||||
usbd_transfer_poll(sc->sc_xfer, UKBD_N_TRANSFER);
|
||||
|
||||
DELAY(1000); /* delay 1 ms */
|
||||
|
||||
sc->sc_time_ms++;
|
||||
|
||||
/* support repetition of keys: */
|
||||
|
||||
ukbd_interrupt(sc);
|
||||
|
||||
if (!wait)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t
|
||||
ukbd_get_key(struct ukbd_softc *sc, uint8_t wait)
|
||||
{
|
||||
@ -311,24 +333,7 @@ ukbd_get_key(struct ukbd_softc *sc, uint8_t wait)
|
||||
usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT]);
|
||||
}
|
||||
if (sc->sc_flags & UKBD_FLAG_POLLING) {
|
||||
DPRINTFN(2, "polling\n");
|
||||
|
||||
while (sc->sc_inputs == 0) {
|
||||
|
||||
usbd_transfer_poll(sc->sc_xfer, UKBD_N_TRANSFER);
|
||||
|
||||
DELAY(1000); /* delay 1 ms */
|
||||
|
||||
sc->sc_time_ms++;
|
||||
|
||||
/* support repetition of keys: */
|
||||
|
||||
ukbd_interrupt(sc);
|
||||
|
||||
if (!wait) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ukbd_do_poll(sc, wait);
|
||||
}
|
||||
if (sc->sc_inputs == 0) {
|
||||
c = -1;
|
||||
@ -706,7 +711,15 @@ 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))
|
||||
error = ENXIO;
|
||||
@ -983,6 +996,14 @@ ukbd_lock(keyboard_t *kbd, int lock)
|
||||
static int
|
||||
ukbd_enable(keyboard_t *kbd)
|
||||
{
|
||||
if (!mtx_owned(&Giant)) {
|
||||
/* XXX cludge */
|
||||
int retval;
|
||||
mtx_lock(&Giant);
|
||||
retval = ukbd_enable(kbd);
|
||||
mtx_unlock(&Giant);
|
||||
return (retval);
|
||||
}
|
||||
mtx_assert(&Giant, MA_OWNED);
|
||||
KBD_ACTIVATE(kbd);
|
||||
return (0);
|
||||
@ -992,6 +1013,14 @@ ukbd_enable(keyboard_t *kbd)
|
||||
static int
|
||||
ukbd_disable(keyboard_t *kbd)
|
||||
{
|
||||
if (!mtx_owned(&Giant)) {
|
||||
/* XXX cludge */
|
||||
int retval;
|
||||
mtx_lock(&Giant);
|
||||
retval = ukbd_disable(kbd);
|
||||
mtx_unlock(&Giant);
|
||||
return (retval);
|
||||
}
|
||||
mtx_assert(&Giant, MA_OWNED);
|
||||
KBD_DEACTIVATE(kbd);
|
||||
return (0);
|
||||
@ -1003,14 +1032,26 @@ ukbd_check(keyboard_t *kbd)
|
||||
{
|
||||
struct ukbd_softc *sc = kbd->kb_data;
|
||||
|
||||
if (!mtx_owned(&Giant)) {
|
||||
return (0); /* XXX */
|
||||
if (!KBD_IS_ACTIVE(kbd))
|
||||
return (0);
|
||||
|
||||
if (sc->sc_flags & UKBD_FLAG_POLLING) {
|
||||
if (!mtx_owned(&Giant)) {
|
||||
/* XXX cludge */
|
||||
int retval;
|
||||
mtx_lock(&Giant);
|
||||
retval = ukbd_check(kbd);
|
||||
mtx_unlock(&Giant);
|
||||
return (retval);
|
||||
}
|
||||
ukbd_do_poll(sc, 0);
|
||||
} else {
|
||||
/* XXX the keyboard layer requires Giant */
|
||||
if (!mtx_owned(&Giant))
|
||||
return (0);
|
||||
}
|
||||
mtx_assert(&Giant, MA_OWNED);
|
||||
|
||||
if (!KBD_IS_ACTIVE(kbd)) {
|
||||
return (0);
|
||||
}
|
||||
#ifdef UKBD_EMULATE_ATSCANCODE
|
||||
if (sc->sc_buffered_char[0]) {
|
||||
return (1);
|
||||
@ -1028,14 +1069,25 @@ ukbd_check_char(keyboard_t *kbd)
|
||||
{
|
||||
struct ukbd_softc *sc = kbd->kb_data;
|
||||
|
||||
if (!mtx_owned(&Giant)) {
|
||||
return (0); /* XXX */
|
||||
if (!KBD_IS_ACTIVE(kbd))
|
||||
return (0);
|
||||
|
||||
if (sc->sc_flags & UKBD_FLAG_POLLING) {
|
||||
if (!mtx_owned(&Giant)) {
|
||||
/* XXX cludge */
|
||||
int retval;
|
||||
mtx_lock(&Giant);
|
||||
retval = ukbd_check_char(kbd);
|
||||
mtx_unlock(&Giant);
|
||||
return (retval);
|
||||
}
|
||||
} else {
|
||||
/* XXX the keyboard layer requires Giant */
|
||||
if (!mtx_owned(&Giant))
|
||||
return (0);
|
||||
}
|
||||
mtx_assert(&Giant, MA_OWNED);
|
||||
|
||||
if (!KBD_IS_ACTIVE(kbd)) {
|
||||
return (0);
|
||||
}
|
||||
if ((sc->sc_composed_char > 0) &&
|
||||
(!(sc->sc_flags & UKBD_FLAG_COMPOSE))) {
|
||||
return (1);
|
||||
@ -1056,9 +1108,22 @@ ukbd_read(keyboard_t *kbd, int wait)
|
||||
uint32_t scancode;
|
||||
|
||||
#endif
|
||||
if (!KBD_IS_ACTIVE(kbd))
|
||||
return (-1);
|
||||
|
||||
if (!mtx_owned(&Giant)) {
|
||||
return -1; /* XXX */
|
||||
if (sc->sc_flags & UKBD_FLAG_POLLING) {
|
||||
if (!mtx_owned(&Giant)) {
|
||||
/* XXX cludge */
|
||||
int retval;
|
||||
mtx_lock(&Giant);
|
||||
retval = ukbd_read(kbd, wait);
|
||||
mtx_unlock(&Giant);
|
||||
return (retval);
|
||||
}
|
||||
} else {
|
||||
/* XXX the keyboard layer requires Giant */
|
||||
if (!mtx_owned(&Giant))
|
||||
return (-1);
|
||||
}
|
||||
mtx_assert(&Giant, MA_OWNED);
|
||||
|
||||
@ -1077,9 +1142,9 @@ ukbd_read(keyboard_t *kbd, int wait)
|
||||
|
||||
/* XXX */
|
||||
usbcode = ukbd_get_key(sc, (wait == FALSE) ? 0 : 1);
|
||||
if (!KBD_IS_ACTIVE(kbd) || (usbcode == -1)) {
|
||||
return -1;
|
||||
}
|
||||
if (!KBD_IS_ACTIVE(kbd) || (usbcode == -1))
|
||||
return (-1);
|
||||
|
||||
++(kbd->kb_count);
|
||||
|
||||
#ifdef UKBD_EMULATE_ATSCANCODE
|
||||
@ -1107,8 +1172,23 @@ ukbd_read_char(keyboard_t *kbd, int wait)
|
||||
uint32_t scancode;
|
||||
|
||||
#endif
|
||||
if (!mtx_owned(&Giant)) {
|
||||
return (NOKEY); /* XXX */
|
||||
|
||||
if (!KBD_IS_ACTIVE(kbd))
|
||||
return (NOKEY);
|
||||
|
||||
if (sc->sc_flags & UKBD_FLAG_POLLING) {
|
||||
if (!mtx_owned(&Giant)) {
|
||||
/* XXX cludge */
|
||||
int retval;
|
||||
mtx_lock(&Giant);
|
||||
retval = ukbd_read_char(kbd, wait);
|
||||
mtx_unlock(&Giant);
|
||||
return (retval);
|
||||
}
|
||||
} else {
|
||||
/* XXX the keyboard layer requires Giant */
|
||||
if (!mtx_owned(&Giant))
|
||||
return (NOKEY);
|
||||
}
|
||||
mtx_assert(&Giant, MA_OWNED);
|
||||
|
||||
@ -1485,7 +1565,12 @@ ukbd_poll(keyboard_t *kbd, int on)
|
||||
struct ukbd_softc *sc = kbd->kb_data;
|
||||
|
||||
if (!mtx_owned(&Giant)) {
|
||||
return (0); /* XXX */
|
||||
/* XXX cludge */
|
||||
int retval;
|
||||
mtx_lock(&Giant);
|
||||
retval = ukbd_poll(kbd, on);
|
||||
mtx_unlock(&Giant);
|
||||
return (retval);
|
||||
}
|
||||
mtx_assert(&Giant, MA_OWNED);
|
||||
|
||||
|
@ -99,6 +99,9 @@ struct usb_bus_methods {
|
||||
void (*set_stall) (struct usb_device *udev, struct usb_xfer *xfer, struct usb_endpoint *ep, uint8_t *did_stall);
|
||||
void (*clear_stall) (struct usb_device *udev, struct usb_endpoint *ep);
|
||||
|
||||
/* Optional transfer polling support */
|
||||
|
||||
void (*xfer_poll) (struct usb_bus *);
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -2853,15 +2853,99 @@ usbd_clear_stall_callback(struct usb_xfer *xfer1,
|
||||
return (1); /* Clear Stall Finished */
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usbd_transfer_poll
|
||||
*
|
||||
* The following function gets called from the USB keyboard driver and
|
||||
* UMASS when the system has paniced.
|
||||
*
|
||||
* NOTE: It is currently not possible to resume normal operation on
|
||||
* the USB controller which has been polled, due to clearing of the
|
||||
* "up_dsleep" and "up_msleep" flags.
|
||||
*------------------------------------------------------------------------*/
|
||||
void
|
||||
usbd_transfer_poll(struct usb_xfer **ppxfer, uint16_t max)
|
||||
{
|
||||
static uint8_t once = 0;
|
||||
/* polling is currently not supported */
|
||||
if (!once) {
|
||||
once = 1;
|
||||
printf("usbd_transfer_poll: USB polling is "
|
||||
"not supported!\n");
|
||||
struct usb_xfer *xfer;
|
||||
struct usb_xfer_root *xroot;
|
||||
struct usb_device *udev;
|
||||
struct usb_proc_msg *pm;
|
||||
uint16_t n;
|
||||
uint16_t drop_bus;
|
||||
uint16_t drop_xfer;
|
||||
|
||||
for (n = 0; n != max; n++) {
|
||||
/* Extra checks to avoid panic */
|
||||
xfer = ppxfer[n];
|
||||
if (xfer == NULL)
|
||||
continue; /* no USB transfer */
|
||||
xroot = xfer->xroot;
|
||||
if (xroot == NULL)
|
||||
continue; /* no USB root */
|
||||
udev = xroot->udev;
|
||||
if (udev == NULL)
|
||||
continue; /* no USB device */
|
||||
if (udev->bus == NULL)
|
||||
continue; /* no BUS structure */
|
||||
if (udev->bus->methods == NULL)
|
||||
continue; /* no BUS methods */
|
||||
if (udev->bus->methods->xfer_poll == NULL)
|
||||
continue; /* no poll method */
|
||||
|
||||
/* make sure that the BUS mutex is not locked */
|
||||
drop_bus = 0;
|
||||
while (mtx_owned(&xroot->udev->bus->bus_mtx)) {
|
||||
mtx_unlock(&xroot->udev->bus->bus_mtx);
|
||||
drop_bus++;
|
||||
}
|
||||
|
||||
/* make sure that the transfer mutex is not locked */
|
||||
drop_xfer = 0;
|
||||
while (mtx_owned(xroot->xfer_mtx)) {
|
||||
mtx_unlock(xroot->xfer_mtx);
|
||||
drop_xfer++;
|
||||
}
|
||||
|
||||
/* Make sure cv_signal() and cv_broadcast() is not called */
|
||||
udev->bus->control_xfer_proc.up_dsleep = 0;
|
||||
udev->bus->control_xfer_proc.up_msleep = 0;
|
||||
udev->bus->explore_proc.up_dsleep = 0;
|
||||
udev->bus->explore_proc.up_msleep = 0;
|
||||
udev->bus->giant_callback_proc.up_dsleep = 0;
|
||||
udev->bus->giant_callback_proc.up_msleep = 0;
|
||||
udev->bus->non_giant_callback_proc.up_dsleep = 0;
|
||||
udev->bus->non_giant_callback_proc.up_msleep = 0;
|
||||
|
||||
/* poll USB hardware */
|
||||
(udev->bus->methods->xfer_poll) (udev->bus);
|
||||
|
||||
USB_BUS_LOCK(xroot->bus);
|
||||
|
||||
/* check for clear stall */
|
||||
if (udev->default_xfer[1] != NULL) {
|
||||
|
||||
/* poll clear stall start */
|
||||
pm = &udev->cs_msg[0].hdr;
|
||||
(pm->pm_callback) (pm);
|
||||
/* poll clear stall done thread */
|
||||
pm = &udev->default_xfer[1]->
|
||||
xroot->done_m[0].hdr;
|
||||
(pm->pm_callback) (pm);
|
||||
}
|
||||
|
||||
/* poll done thread */
|
||||
pm = &xroot->done_m[0].hdr;
|
||||
(pm->pm_callback) (pm);
|
||||
|
||||
USB_BUS_UNLOCK(xroot->bus);
|
||||
|
||||
/* restore transfer mutex */
|
||||
while (drop_xfer--)
|
||||
mtx_lock(xroot->xfer_mtx);
|
||||
|
||||
/* restore BUS mutex */
|
||||
while (drop_bus--)
|
||||
mtx_lock(&xroot->udev->bus->bus_mtx);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user