summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/dev/usb/usb_hub.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/dev/usb/usb_hub.c')
-rw-r--r--freebsd/sys/dev/usb/usb_hub.c76
1 files changed, 26 insertions, 50 deletions
diff --git a/freebsd/sys/dev/usb/usb_hub.c b/freebsd/sys/dev/usb/usb_hub.c
index a0ad462f..b3543a8f 100644
--- a/freebsd/sys/dev/usb/usb_hub.c
+++ b/freebsd/sys/dev/usb/usb_hub.c
@@ -77,14 +77,9 @@
#include <dev/usb/usb_bus.h>
#endif /* USB_GLOBAL_INCLUDE_FILE */
-#define UHUB_INTR_INTERVAL 250 /* ms */
-enum {
- UHUB_INTR_TRANSFER,
-#if USB_HAVE_TT_SUPPORT
- UHUB_RESET_TT_TRANSFER,
-#endif
- UHUB_N_TRANSFER,
-};
+
+#include <dev/usb/usb_hub_private.h>
+
#ifdef USB_DEBUG
static int uhub_debug = 0;
@@ -113,27 +108,6 @@ SYSCTL_INT(_hw_usb, OID_AUTO, disable_port_power, CTLFLAG_RWTUN,
&usb_disable_port_power, 0, "Set to disable all USB port power.");
#endif
-struct uhub_current_state {
- uint16_t port_change;
- uint16_t port_status;
-};
-
-struct uhub_softc {
- struct uhub_current_state sc_st;/* current state */
-#if (USB_HAVE_FIXED_PORT != 0)
- struct usb_hub sc_hub;
-#endif
- device_t sc_dev; /* base device */
- struct mtx sc_mtx; /* our mutex */
- struct usb_device *sc_udev; /* USB device */
- struct usb_xfer *sc_xfer[UHUB_N_TRANSFER]; /* interrupt xfer */
-#if USB_HAVE_DISABLE_ENUM
- int sc_disable_enumeration;
- int sc_disable_port_power;
-#endif
- uint8_t sc_flags;
-#define UHUB_FLAG_DID_EXPLORE 0x01
-};
#define UHUB_PROTO(sc) ((sc)->sc_udev->ddesc.bDeviceProtocol)
#define UHUB_IS_HIGH_SPEED(sc) (UHUB_PROTO(sc) != UDPROTO_FSHUB)
@@ -143,14 +117,10 @@ struct uhub_softc {
/* prototypes for type checking: */
-static device_probe_t uhub_probe;
-static device_attach_t uhub_attach;
-static device_detach_t uhub_detach;
static device_suspend_t uhub_suspend;
static device_resume_t uhub_resume;
static bus_driver_added_t uhub_driver_added;
-static bus_child_location_str_t uhub_child_location_string;
static bus_child_pnpinfo_str_t uhub_child_pnpinfo_string;
static usb_callback_t uhub_intr_callback;
@@ -207,7 +177,7 @@ static device_method_t uhub_methods[] = {
DEVMETHOD_END
};
-static driver_t uhub_driver = {
+driver_t uhub_driver = {
.name = "uhub",
.methods = uhub_methods,
.size = sizeof(struct uhub_softc)
@@ -589,13 +559,25 @@ uhub_read_port_status(struct uhub_softc *sc, uint8_t portno)
struct usb_port_status ps;
usb_error_t err;
+ if (sc->sc_usb_port_errors >= UHUB_USB_PORT_ERRORS_MAX) {
+ DPRINTFN(4, "port %d, HUB looks dead, too many errors\n", portno);
+ sc->sc_st.port_status = 0;
+ sc->sc_st.port_change = 0;
+ return (USB_ERR_TIMEOUT);
+ }
+
err = usbd_req_get_port_status(
sc->sc_udev, NULL, &ps, portno);
- /* update status regardless of error */
-
- sc->sc_st.port_status = UGETW(ps.wPortStatus);
- sc->sc_st.port_change = UGETW(ps.wPortChange);
+ if (err == 0) {
+ sc->sc_st.port_status = UGETW(ps.wPortStatus);
+ sc->sc_st.port_change = UGETW(ps.wPortChange);
+ sc->sc_usb_port_errors = 0;
+ } else {
+ sc->sc_st.port_status = 0;
+ sc->sc_st.port_change = 0;
+ sc->sc_usb_port_errors++;
+ }
/* debugging print */
@@ -1126,7 +1108,7 @@ uhub_explore(struct usb_device *udev)
return (USB_ERR_NORMAL_COMPLETION);
}
-static int
+int
uhub_probe(device_t dev)
{
struct usb_attach_arg *uaa = device_get_ivars(dev);
@@ -1140,7 +1122,7 @@ uhub_probe(device_t dev)
*/
if (uaa->info.bConfigIndex == 0 &&
uaa->info.bDeviceClass == UDCLASS_HUB)
- return (0);
+ return (BUS_PROBE_DEFAULT);
return (ENXIO);
}
@@ -1206,7 +1188,7 @@ uhub_query_info(struct usb_device *udev, uint8_t *pnports, uint8_t *ptt)
return (err);
}
-static int
+int
uhub_attach(device_t dev)
{
struct uhub_softc *sc = device_get_softc(dev);
@@ -1552,7 +1534,7 @@ error:
* Called from process context when the hub is gone.
* Detach all devices on active ports.
*/
-static int
+int
uhub_detach(device_t dev)
{
struct uhub_softc *sc = device_get_softc(dev);
@@ -1622,13 +1604,7 @@ uhub_driver_added(device_t dev, driver_t *driver)
usb_needs_explore_all();
}
-struct hub_result {
- struct usb_device *udev;
- uint8_t portno;
- uint8_t iface_index;
-};
-
-static void
+void
uhub_find_iface_index(struct usb_hub *hub, device_t child,
struct hub_result *res)
{
@@ -1661,7 +1637,7 @@ uhub_find_iface_index(struct usb_hub *hub, device_t child,
res->portno = 0;
}
-static int
+int
uhub_child_location_string(device_t parent, device_t child,
char *buf, size_t buflen)
{