Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/usb/usb_hub.c
Show First 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | |||||
#include <dev/usb/usb_busdma.h> | #include <dev/usb/usb_busdma.h> | ||||
#include <dev/usb/usb_transfer.h> | #include <dev/usb/usb_transfer.h> | ||||
#include <dev/usb/usb_dynamic.h> | #include <dev/usb/usb_dynamic.h> | ||||
#include <dev/usb/usb_controller.h> | #include <dev/usb/usb_controller.h> | ||||
#include <dev/usb/usb_bus.h> | #include <dev/usb/usb_bus.h> | ||||
#endif /* USB_GLOBAL_INCLUDE_FILE */ | #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 | #ifdef USB_DEBUG | ||||
static int uhub_debug = 0; | static int uhub_debug = 0; | ||||
static SYSCTL_NODE(_hw_usb, OID_AUTO, uhub, CTLFLAG_RW, 0, "USB HUB"); | static SYSCTL_NODE(_hw_usb, OID_AUTO, uhub, CTLFLAG_RW, 0, "USB HUB"); | ||||
SYSCTL_INT(_hw_usb_uhub, OID_AUTO, debug, CTLFLAG_RWTUN, &uhub_debug, 0, | SYSCTL_INT(_hw_usb_uhub, OID_AUTO, debug, CTLFLAG_RWTUN, &uhub_debug, 0, | ||||
"Debug level"); | "Debug level"); | ||||
#endif | #endif | ||||
Show All 11 Lines | SYSCTL_INT(_hw_usb, OID_AUTO, disable_enumeration, CTLFLAG_RWTUN, | ||||
"This can secure against USB devices turning evil, " | "This can secure against USB devices turning evil, " | ||||
"for example a USB memory stick becoming a USB keyboard."); | "for example a USB memory stick becoming a USB keyboard."); | ||||
static int usb_disable_port_power = 0; | static int usb_disable_port_power = 0; | ||||
SYSCTL_INT(_hw_usb, OID_AUTO, disable_port_power, CTLFLAG_RWTUN, | SYSCTL_INT(_hw_usb, OID_AUTO, disable_port_power, CTLFLAG_RWTUN, | ||||
&usb_disable_port_power, 0, "Set to disable all USB port power."); | &usb_disable_port_power, 0, "Set to disable all USB port power."); | ||||
#endif | #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_usb_port_errors; /* error counter */ | |||||
#define UHUB_USB_PORT_ERRORS_MAX 4 | |||||
uint8_t sc_flags; | |||||
#define UHUB_FLAG_DID_EXPLORE 0x01 | |||||
}; | |||||
#define UHUB_PROTO(sc) ((sc)->sc_udev->ddesc.bDeviceProtocol) | #define UHUB_PROTO(sc) ((sc)->sc_udev->ddesc.bDeviceProtocol) | ||||
#define UHUB_IS_HIGH_SPEED(sc) (UHUB_PROTO(sc) != UDPROTO_FSHUB) | #define UHUB_IS_HIGH_SPEED(sc) (UHUB_PROTO(sc) != UDPROTO_FSHUB) | ||||
#define UHUB_IS_SINGLE_TT(sc) (UHUB_PROTO(sc) == UDPROTO_HSHUBSTT) | #define UHUB_IS_SINGLE_TT(sc) (UHUB_PROTO(sc) == UDPROTO_HSHUBSTT) | ||||
#define UHUB_IS_MULTI_TT(sc) (UHUB_PROTO(sc) == UDPROTO_HSHUBMTT) | #define UHUB_IS_MULTI_TT(sc) (UHUB_PROTO(sc) == UDPROTO_HSHUBMTT) | ||||
#define UHUB_IS_SUPER_SPEED(sc) (UHUB_PROTO(sc) == UDPROTO_SSHUB) | #define UHUB_IS_SUPER_SPEED(sc) (UHUB_PROTO(sc) == UDPROTO_SSHUB) | ||||
/* prototypes for type checking: */ | /* 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_suspend_t uhub_suspend; | ||||
static device_resume_t uhub_resume; | static device_resume_t uhub_resume; | ||||
static bus_driver_added_t uhub_driver_added; | 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 bus_child_pnpinfo_str_t uhub_child_pnpinfo_string; | ||||
static usb_callback_t uhub_intr_callback; | static usb_callback_t uhub_intr_callback; | ||||
#if USB_HAVE_TT_SUPPORT | #if USB_HAVE_TT_SUPPORT | ||||
static usb_callback_t uhub_reset_tt_callback; | static usb_callback_t uhub_reset_tt_callback; | ||||
#endif | #endif | ||||
static void usb_dev_resume_peer(struct usb_device *udev); | static void usb_dev_resume_peer(struct usb_device *udev); | ||||
Show All 40 Lines | static device_method_t uhub_methods[] = { | ||||
DEVMETHOD(device_resume, uhub_resume), | DEVMETHOD(device_resume, uhub_resume), | ||||
DEVMETHOD(bus_child_location_str, uhub_child_location_string), | DEVMETHOD(bus_child_location_str, uhub_child_location_string), | ||||
DEVMETHOD(bus_child_pnpinfo_str, uhub_child_pnpinfo_string), | DEVMETHOD(bus_child_pnpinfo_str, uhub_child_pnpinfo_string), | ||||
DEVMETHOD(bus_driver_added, uhub_driver_added), | DEVMETHOD(bus_driver_added, uhub_driver_added), | ||||
DEVMETHOD_END | DEVMETHOD_END | ||||
}; | }; | ||||
static driver_t uhub_driver = { | driver_t uhub_driver = { | ||||
.name = "uhub", | .name = "uhub", | ||||
.methods = uhub_methods, | .methods = uhub_methods, | ||||
.size = sizeof(struct uhub_softc) | .size = sizeof(struct uhub_softc) | ||||
}; | }; | ||||
DRIVER_MODULE(uhub, usbus, uhub_driver, uhub_devclass, 0, 0); | DRIVER_MODULE(uhub, usbus, uhub_driver, uhub_devclass, 0, 0); | ||||
DRIVER_MODULE(uhub, uhub, uhub_driver, uhub_devclass, NULL, 0); | DRIVER_MODULE(uhub, uhub, uhub_driver, uhub_devclass, NULL, 0); | ||||
MODULE_VERSION(uhub, 1); | MODULE_VERSION(uhub, 1); | ||||
▲ Show 20 Lines • Show All 914 Lines • ▼ Show 20 Lines | uhub_explore(struct usb_device *udev) | ||||
/* initial status checked */ | /* initial status checked */ | ||||
sc->sc_flags |= UHUB_FLAG_DID_EXPLORE; | sc->sc_flags |= UHUB_FLAG_DID_EXPLORE; | ||||
/* return success */ | /* return success */ | ||||
return (USB_ERR_NORMAL_COMPLETION); | return (USB_ERR_NORMAL_COMPLETION); | ||||
} | } | ||||
static int | int | ||||
uhub_probe(device_t dev) | uhub_probe(device_t dev) | ||||
{ | { | ||||
struct usb_attach_arg *uaa = device_get_ivars(dev); | struct usb_attach_arg *uaa = device_get_ivars(dev); | ||||
if (uaa->usb_mode != USB_MODE_HOST) | if (uaa->usb_mode != USB_MODE_HOST) | ||||
return (ENXIO); | return (ENXIO); | ||||
/* | /* | ||||
* The subclass for USB HUBs is currently ignored because it | * The subclass for USB HUBs is currently ignored because it | ||||
* is 0 for some and 1 for others. | * is 0 for some and 1 for others. | ||||
*/ | */ | ||||
if (uaa->info.bConfigIndex == 0 && | if (uaa->info.bConfigIndex == 0 && | ||||
uaa->info.bDeviceClass == UDCLASS_HUB) | uaa->info.bDeviceClass == UDCLASS_HUB) | ||||
return (0); | return (BUS_PROBE_DEFAULT); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
/* NOTE: The information returned by this function can be wrong. */ | /* NOTE: The information returned by this function can be wrong. */ | ||||
usb_error_t | usb_error_t | ||||
uhub_query_info(struct usb_device *udev, uint8_t *pnports, uint8_t *ptt) | uhub_query_info(struct usb_device *udev, uint8_t *pnports, uint8_t *ptt) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | if (pnports != NULL) | ||||
*pnports = nports; | *pnports = nports; | ||||
if (ptt != NULL) | if (ptt != NULL) | ||||
*ptt = tt; | *ptt = tt; | ||||
return (err); | return (err); | ||||
} | } | ||||
static int | int | ||||
uhub_attach(device_t dev) | uhub_attach(device_t dev) | ||||
{ | { | ||||
struct uhub_softc *sc = device_get_softc(dev); | struct uhub_softc *sc = device_get_softc(dev); | ||||
struct usb_attach_arg *uaa = device_get_ivars(dev); | struct usb_attach_arg *uaa = device_get_ivars(dev); | ||||
struct usb_device *udev = uaa->device; | struct usb_device *udev = uaa->device; | ||||
struct usb_device *parent_hub = udev->parent_hub; | struct usb_device *parent_hub = udev->parent_hub; | ||||
struct usb_hub *hub; | struct usb_hub *hub; | ||||
struct usb_hub_descriptor hubdesc20; | struct usb_hub_descriptor hubdesc20; | ||||
▲ Show 20 Lines • Show All 329 Lines • ▼ Show 20 Lines | #endif | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
/* | /* | ||||
* Called from process context when the hub is gone. | * Called from process context when the hub is gone. | ||||
* Detach all devices on active ports. | * Detach all devices on active ports. | ||||
*/ | */ | ||||
static int | int | ||||
uhub_detach(device_t dev) | uhub_detach(device_t dev) | ||||
{ | { | ||||
struct uhub_softc *sc = device_get_softc(dev); | struct uhub_softc *sc = device_get_softc(dev); | ||||
struct usb_hub *hub = sc->sc_udev->hub; | struct usb_hub *hub = sc->sc_udev->hub; | ||||
struct usb_bus *bus = sc->sc_udev->bus; | struct usb_bus *bus = sc->sc_udev->bus; | ||||
struct usb_device *child; | struct usb_device *child; | ||||
uint8_t x; | uint8_t x; | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static void | static void | ||||
uhub_driver_added(device_t dev, driver_t *driver) | uhub_driver_added(device_t dev, driver_t *driver) | ||||
{ | { | ||||
usb_needs_explore_all(); | usb_needs_explore_all(); | ||||
} | } | ||||
struct hub_result { | void | ||||
struct usb_device *udev; | |||||
uint8_t portno; | |||||
uint8_t iface_index; | |||||
}; | |||||
static void | |||||
uhub_find_iface_index(struct usb_hub *hub, device_t child, | uhub_find_iface_index(struct usb_hub *hub, device_t child, | ||||
struct hub_result *res) | struct hub_result *res) | ||||
{ | { | ||||
struct usb_interface *iface; | struct usb_interface *iface; | ||||
struct usb_device *udev; | struct usb_device *udev; | ||||
uint8_t nports; | uint8_t nports; | ||||
uint8_t x; | uint8_t x; | ||||
uint8_t i; | uint8_t i; | ||||
Show All 16 Lines | for (i = 0; i != USB_IFACE_MAX; i++) { | ||||
} | } | ||||
} | } | ||||
} | } | ||||
res->iface_index = 0; | res->iface_index = 0; | ||||
res->udev = NULL; | res->udev = NULL; | ||||
res->portno = 0; | res->portno = 0; | ||||
} | } | ||||
static int | int | ||||
uhub_child_location_string(device_t parent, device_t child, | uhub_child_location_string(device_t parent, device_t child, | ||||
char *buf, size_t buflen) | char *buf, size_t buflen) | ||||
{ | { | ||||
struct uhub_softc *sc; | struct uhub_softc *sc; | ||||
struct usb_hub *hub; | struct usb_hub *hub; | ||||
struct hub_result res; | struct hub_result res; | ||||
if (!device_is_attached(parent)) { | if (!device_is_attached(parent)) { | ||||
▲ Show 20 Lines • Show All 1,283 Lines • Show Last 20 Lines |