aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/usb/serial/u3g.c54
-rw-r--r--sys/dev/usb/usb_device.c151
-rw-r--r--sys/dev/usb/usb_dynamic.c23
-rw-r--r--sys/dev/usb/usb_dynamic.h4
-rw-r--r--sys/dev/usb/usbdi.h12
5 files changed, 112 insertions, 132 deletions
diff --git a/sys/dev/usb/serial/u3g.c b/sys/dev/usb/serial/u3g.c
index ea40ea6fa100..cb00671ce487 100644
--- a/sys/dev/usb/serial/u3g.c
+++ b/sys/dev/usb/serial/u3g.c
@@ -122,8 +122,13 @@ static void u3g_stop_read(struct ucom_softc *ucom);
static void u3g_start_write(struct ucom_softc *ucom);
static void u3g_stop_write(struct ucom_softc *ucom);
+
+static void u3g_test_autoinst(void *, struct usb_device *,
+ struct usb_attach_arg *);
static int u3g_driver_loaded(struct module *mod, int what, void *arg);
+static eventhandler_tag u3g_etag;
+
static const struct usb_config u3g_config[U3G_N_TRANSFER] = {
[U3G_BULK_WR] = {
@@ -360,58 +365,48 @@ u3g_sael_m460_init(struct usb_device *udev)
}
}
-static int
-u3g_lookup_huawei(struct usb_attach_arg *uaa)
-{
- /* Calling the lookup function will also set the driver info! */
- return (usbd_lookup_id_by_uaa(u3g_devs, sizeof(u3g_devs), uaa));
-}
-
/*
* The following function handles 3G modem devices (E220, Mobile,
* etc.) with auto-install flash disks for Windows/MacOSX on the first
* interface. After some command or some delay they change appearance
* to a modem.
*/
-static usb_error_t
-u3g_test_huawei_autoinst(struct usb_device *udev,
+static void
+u3g_test_autoinst(void *arg, struct usb_device *udev,
struct usb_attach_arg *uaa)
{
struct usb_interface *iface;
struct usb_interface_descriptor *id;
uint32_t flags;
- if (udev == NULL) {
- return (USB_ERR_INVAL);
- }
+ if (uaa->dev_state != UAA_DEV_READY)
+ return;
+
iface = usbd_get_iface(udev, 0);
- if (iface == NULL) {
- return (USB_ERR_INVAL);
- }
+ if (iface == NULL)
+ return;
id = iface->idesc;
- if (id == NULL) {
- return (USB_ERR_INVAL);
- }
- if (id->bInterfaceClass != UICLASS_MASS) {
- return (USB_ERR_INVAL);
- }
- if (u3g_lookup_huawei(uaa)) {
+ if (id == NULL || id->bInterfaceClass != UICLASS_MASS)
+ return;
+ if (usbd_lookup_id_by_uaa(u3g_devs, sizeof(u3g_devs), uaa)) {
/* no device match */
- return (USB_ERR_INVAL);
+ return;
}
flags = USB_GET_DRIVER_INFO(uaa);
if (flags & U3GFL_HUAWEI_INIT) {
u3g_huawei_init(udev);
} else if (flags & U3GFL_SCSI_EJECT) {
- return (usb_test_autoinstall(udev, 0, 1));
+ if (usb_test_autoinstall(udev, 0, 1) != 0)
+ return;
} else if (flags & U3GFL_SIERRA_INIT) {
u3g_sierra_init(udev);
} else {
/* no quirks */
- return (USB_ERR_INVAL);
+ return;
}
- return (0); /* success */
+ uaa->dev_state = UAA_DEV_EJECTING;
+ return; /* success */
}
static int
@@ -420,10 +415,11 @@ u3g_driver_loaded(struct module *mod, int what, void *arg)
switch (what) {
case MOD_LOAD:
/* register our autoinstall handler */
- usb_test_huawei_autoinst_p = &u3g_test_huawei_autoinst;
+ u3g_etag = EVENTHANDLER_REGISTER(usb_dev_configured,
+ u3g_test_autoinst, NULL, EVENTHANDLER_PRI_ANY);
break;
case MOD_UNLOAD:
- usb_test_huawei_unload(NULL);
+ EVENTHANDLER_DEREGISTER(usb_dev_configured, u3g_etag);
break;
default:
return (EOPNOTSUPP);
@@ -445,7 +441,7 @@ u3g_probe(device_t self)
if (uaa->info.bInterfaceClass != UICLASS_VENDOR) {
return (ENXIO);
}
- return (u3g_lookup_huawei(uaa));
+ return (usbd_lookup_id_by_uaa(u3g_devs, sizeof(u3g_devs), uaa));
}
static int
diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c
index 6787fa6ead19..7fdb7e4a2c27 100644
--- a/sys/dev/usb/usb_device.c
+++ b/sys/dev/usb/usb_device.c
@@ -1204,6 +1204,7 @@ usb_init_attach_arg(struct usb_device *udev,
uaa->device = udev;
uaa->usb_mode = udev->flags.usb_mode;
uaa->port = udev->port_no;
+ uaa->dev_state = UAA_DEV_READY;
uaa->info.idVendor = UGETW(udev->ddesc.idVendor);
uaa->info.idProduct = UGETW(udev->ddesc.idProduct);
@@ -1453,6 +1454,9 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus,
size_t scratch_size;
usb_error_t err;
uint8_t device_index;
+ uint8_t config_index;
+ uint8_t config_quirk;
+ uint8_t set_config_failed;
DPRINTF("parent_dev=%p, bus=%p, parent_hub=%p, depth=%u, "
"port_index=%u, port_no=%u, speed=%u, usb_mode=%u\n",
@@ -1732,96 +1736,91 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus,
/* fetch the vendor and product strings from the device */
usbd_set_device_strings(udev);
- if (udev->flags.usb_mode == USB_MODE_HOST) {
- uint8_t config_index;
- uint8_t config_quirk;
- uint8_t set_config_failed = 0;
+ if (udev->flags.usb_mode == USB_MODE_DEVICE) {
+ /* USB device mode setup is complete */
+ err = 0;
+ goto config_done;
+ }
- /*
- * Most USB devices should attach to config index 0 by
- * default
- */
- if (usb_test_quirk(&uaa, UQ_CFG_INDEX_0)) {
- config_index = 0;
- config_quirk = 1;
- } else if (usb_test_quirk(&uaa, UQ_CFG_INDEX_1)) {
- config_index = 1;
- config_quirk = 1;
- } else if (usb_test_quirk(&uaa, UQ_CFG_INDEX_2)) {
- config_index = 2;
- config_quirk = 1;
- } else if (usb_test_quirk(&uaa, UQ_CFG_INDEX_3)) {
- config_index = 3;
- config_quirk = 1;
- } else if (usb_test_quirk(&uaa, UQ_CFG_INDEX_4)) {
- config_index = 4;
- config_quirk = 1;
- } else {
- config_index = 0;
- config_quirk = 0;
- }
+ /*
+ * Most USB devices should attach to config index 0 by
+ * default
+ */
+ if (usb_test_quirk(&uaa, UQ_CFG_INDEX_0)) {
+ config_index = 0;
+ config_quirk = 1;
+ } else if (usb_test_quirk(&uaa, UQ_CFG_INDEX_1)) {
+ config_index = 1;
+ config_quirk = 1;
+ } else if (usb_test_quirk(&uaa, UQ_CFG_INDEX_2)) {
+ config_index = 2;
+ config_quirk = 1;
+ } else if (usb_test_quirk(&uaa, UQ_CFG_INDEX_3)) {
+ config_index = 3;
+ config_quirk = 1;
+ } else if (usb_test_quirk(&uaa, UQ_CFG_INDEX_4)) {
+ config_index = 4;
+ config_quirk = 1;
+ } else {
+ config_index = 0;
+ config_quirk = 0;
+ }
+ set_config_failed = 0;
repeat_set_config:
- DPRINTF("setting config %u\n", config_index);
+ DPRINTF("setting config %u\n", config_index);
- /* get the USB device configured */
- err = usbd_set_config_index(udev, config_index);
- if (err) {
- if (udev->ddesc.bNumConfigurations != 0) {
- if (!set_config_failed) {
- set_config_failed = 1;
- /* XXX try to re-enumerate the device */
- err = usbd_req_re_enumerate(
- udev, NULL);
- if (err == 0)
- goto repeat_set_config;
- }
- DPRINTFN(0, "Failure selecting "
- "configuration index %u: %s, port %u, "
- "addr %u (ignored)\n",
- config_index, usbd_errstr(err), udev->port_no,
- udev->address);
+ /* get the USB device configured */
+ err = usbd_set_config_index(udev, config_index);
+ if (err) {
+ if (udev->ddesc.bNumConfigurations != 0) {
+ if (!set_config_failed) {
+ set_config_failed = 1;
+ /* XXX try to re-enumerate the device */
+ err = usbd_req_re_enumerate(udev, NULL);
+ if (err == 0)
+ goto repeat_set_config;
}
+ DPRINTFN(0, "Failure selecting configuration index %u:"
+ "%s, port %u, addr %u (ignored)\n",
+ config_index, usbd_errstr(err), udev->port_no,
+ udev->address);
+ }
+ /*
+ * Some USB devices do not have any configurations. Ignore any
+ * set config failures!
+ */
+ err = 0;
+ goto config_done;
+ }
+ if (!config_quirk && config_index + 1 < udev->ddesc.bNumConfigurations) {
+ if ((udev->cdesc->bNumInterface < 2) &&
+ usbd_get_no_descriptors(udev->cdesc, UDESC_ENDPOINT) == 0) {
+ DPRINTFN(0, "Found no endpoints, trying next config\n");
+ config_index++;
+ goto repeat_set_config;
+ }
+ if (config_index == 0) {
/*
- * Some USB devices do not have any
- * configurations. Ignore any set config
- * failures!
+ * Try to figure out if we have an
+ * auto-install disk there:
*/
- err = 0;
- } else if (config_quirk) {
- /* user quirk selects configuration index */
- } else if ((config_index + 1) < udev->ddesc.bNumConfigurations) {
-
- if ((udev->cdesc->bNumInterface < 2) &&
- (usbd_get_no_descriptors(udev->cdesc,
- UDESC_ENDPOINT) == 0)) {
- DPRINTFN(0, "Found no endpoints "
- "(trying next config)\n");
+ if (usb_test_autoinstall(udev, 0, 0) == 0) {
+ DPRINTFN(0, "Found possible auto-install "
+ "disk (trying next config)\n");
config_index++;
goto repeat_set_config;
}
- if (config_index == 0) {
- /*
- * Try to figure out if we have an
- * auto-install disk there:
- */
- if (usb_test_autoinstall(udev, 0, 0) == 0) {
- DPRINTFN(0, "Found possible auto-install "
- "disk (trying next config)\n");
- config_index++;
- goto repeat_set_config;
- }
- }
- } else if (usb_test_huawei_autoinst_p(udev, &uaa) == 0) {
- DPRINTFN(0, "Found Huawei auto-install disk\n");
- /* leave device unconfigured */
- usb_unconfigure(udev, 0);
}
- } else {
- err = 0; /* set success */
+ }
+ EVENTHANDLER_INVOKE(usb_dev_configured, udev, &uaa);
+ if (uaa.dev_state != UAA_DEV_READY) {
+ /* leave device unconfigured */
+ usb_unconfigure(udev, 0);
}
+config_done:
DPRINTF("new dev (addr %d), udev=%p, parent_hub=%p\n",
udev->address, udev, udev->parent_hub);
diff --git a/sys/dev/usb/usb_dynamic.c b/sys/dev/usb/usb_dynamic.c
index b64712fc3406..add01ce282c8 100644
--- a/sys/dev/usb/usb_dynamic.c
+++ b/sys/dev/usb/usb_dynamic.c
@@ -57,7 +57,6 @@ static usb_handle_req_t usb_temp_get_desc_w;
static usb_temp_setup_by_index_t usb_temp_setup_by_index_w;
static usb_temp_unsetup_t usb_temp_unsetup_w;
static usb_test_quirk_t usb_test_quirk_w;
-static usb_test_huawei_autoinst_t usb_test_huawei_autoinst_w;
static usb_quirk_ioctl_t usb_quirk_ioctl_w;
/* global variables */
@@ -65,7 +64,6 @@ usb_handle_req_t *usb_temp_get_desc_p = &usb_temp_get_desc_w;
usb_temp_setup_by_index_t *usb_temp_setup_by_index_p = &usb_temp_setup_by_index_w;
usb_temp_unsetup_t *usb_temp_unsetup_p = &usb_temp_unsetup_w;
usb_test_quirk_t *usb_test_quirk_p = &usb_test_quirk_w;
-usb_test_huawei_autoinst_t *usb_test_huawei_autoinst_p = &usb_test_huawei_autoinst_w;
usb_quirk_ioctl_t *usb_quirk_ioctl_p = &usb_quirk_ioctl_w;
devclass_t usb_devclass_ptr = NULL;
@@ -105,13 +103,6 @@ usb_temp_unsetup_w(struct usb_device *udev)
}
}
-static usb_error_t
-usb_test_huawei_autoinst_w(struct usb_device *udev,
- struct usb_attach_arg *uaa)
-{
- return (USB_ERR_INVAL);
-}
-
void
usb_quirk_unload(void *arg)
{
@@ -156,17 +147,3 @@ usb_bus_unload(void *arg)
pause("WAIT", hz);
}
-
-void
-usb_test_huawei_unload(void *arg)
-{
- /* reset function pointers */
-
- usb_test_huawei_autoinst_p = &usb_test_huawei_autoinst_w;
-
- /* wait for CPU to exit the loaded functions, if any */
-
- /* XXX this is a tradeoff */
-
- pause("WAIT", 16*hz);
-}
diff --git a/sys/dev/usb/usb_dynamic.h b/sys/dev/usb/usb_dynamic.h
index f8b7caf69f3c..568494204c17 100644
--- a/sys/dev/usb/usb_dynamic.h
+++ b/sys/dev/usb/usb_dynamic.h
@@ -37,8 +37,6 @@ struct usb_device_request;
typedef usb_error_t (usb_temp_setup_by_index_t)(struct usb_device *udev,
uint16_t index);
-typedef usb_error_t (usb_test_huawei_autoinst_t)(struct usb_device *udev,
- struct usb_attach_arg *uaa);
typedef uint8_t (usb_test_quirk_t)(const struct usbd_lookup_info *info,
uint16_t quirk);
typedef int (usb_quirk_ioctl_t)(unsigned long cmd, caddr_t data,
@@ -51,13 +49,11 @@ extern usb_handle_req_t *usb_temp_get_desc_p;
extern usb_temp_setup_by_index_t *usb_temp_setup_by_index_p;
extern usb_temp_unsetup_t *usb_temp_unsetup_p;
extern usb_test_quirk_t *usb_test_quirk_p;
-extern usb_test_huawei_autoinst_t *usb_test_huawei_autoinst_p;
extern usb_quirk_ioctl_t *usb_quirk_ioctl_p;
extern devclass_t usb_devclass_ptr;
/* function prototypes */
-void usb_test_huawei_unload(void *);
void usb_temp_unload(void *);
void usb_quirk_unload(void *);
void usb_bus_unload(void *);
diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h
index 1a6665227beb..9adf39adc776 100644
--- a/sys/dev/usb/usbdi.h
+++ b/sys/dev/usb/usbdi.h
@@ -29,6 +29,7 @@
struct usb_fifo;
struct usb_xfer;
struct usb_device;
+struct usb_attach_arg;
struct usb_interface;
struct usb_endpoint;
struct usb_page_cache;
@@ -98,6 +99,13 @@ typedef int (usb_fifo_ioctl_t)(struct usb_fifo *fifo, u_long cmd, void *addr, in
typedef void (usb_fifo_cmd_t)(struct usb_fifo *fifo);
typedef void (usb_fifo_filter_t)(struct usb_fifo *fifo, struct usb_mbuf *m);
+
+/* USB events */
+#include <sys/eventhandler.h>
+typedef void (*usb_dev_configured_t)(void *, struct usb_device *,
+ struct usb_attach_arg *);
+EVENTHANDLER_DECLARE(usb_dev_configured, usb_dev_configured_t);
+
/*
* The following macros are used used to convert milliseconds into
* HZ. We use 1024 instead of 1000 milliseconds per second to save a
@@ -338,6 +346,10 @@ struct usb_attach_arg {
enum usb_hc_mode usb_mode; /* host or device mode */
uint8_t port;
uint8_t use_generic; /* hint for generic drivers */
+ uint8_t dev_state;
+#define UAA_DEV_READY 0
+#define UAA_DEV_DISABLED 1
+#define UAA_DEV_EJECTING 2
};
/*