Exemplo n.º 1
0
/*------------------------------------------------------------------------*
 *	usb_attach_sub
 *
 * This function creates a thread which runs the USB attach code.
 *------------------------------------------------------------------------*/
static void
usb_attach_sub(device_t dev, struct usb_bus *bus)
{
	const char *pname = device_get_nameunit(dev);

	mtx_lock(&Giant);
	if (usb_devclass_ptr == NULL)
		usb_devclass_ptr = devclass_find("usbus");
	mtx_unlock(&Giant);

#if USB_HAVE_PF
	usbpf_attach(bus);
#endif
	/* Initialise USB process messages */
	bus->explore_msg[0].hdr.pm_callback = &usb_bus_explore;
	bus->explore_msg[0].bus = bus;
	bus->explore_msg[1].hdr.pm_callback = &usb_bus_explore;
	bus->explore_msg[1].bus = bus;

	bus->detach_msg[0].hdr.pm_callback = &usb_bus_detach;
	bus->detach_msg[0].bus = bus;
	bus->detach_msg[1].hdr.pm_callback = &usb_bus_detach;
	bus->detach_msg[1].bus = bus;

	bus->attach_msg[0].hdr.pm_callback = &usb_bus_attach;
	bus->attach_msg[0].bus = bus;
	bus->attach_msg[1].hdr.pm_callback = &usb_bus_attach;
	bus->attach_msg[1].bus = bus;

	/* Create USB explore and callback processes */

	if (usb_proc_create(&bus->giant_callback_proc,
	    &bus->bus_mtx, pname, USB_PRI_MED)) {
		device_printf(dev, "WARNING: Creation of USB Giant "
		    "callback process failed.\n");
	} else if (usb_proc_create(&bus->non_giant_callback_proc,
	    &bus->bus_mtx, pname, USB_PRI_HIGH)) {
		device_printf(dev, "WARNING: Creation of USB non-Giant "
		    "callback process failed.\n");
	} else if (usb_proc_create(&bus->explore_proc,
	    &bus->bus_mtx, pname, USB_PRI_MED)) {
		device_printf(dev, "WARNING: Creation of USB explore "
		    "process failed.\n");
	} else if (usb_proc_create(&bus->control_xfer_proc,
	    &bus->bus_mtx, pname, USB_PRI_MED)) {
		device_printf(dev, "WARNING: Creation of USB control transfer "
		    "process failed.\n");
	} else {
		/* Get final attach going */
		USB_BUS_LOCK(bus);
		if (usb_proc_msignal(&bus->explore_proc,
		    &bus->attach_msg[0], &bus->attach_msg[1])) {
			/* ignore */
		}
		USB_BUS_UNLOCK(bus);

		/* Do initial explore */
		usb_needs_explore(bus, 1);
	}
}
Exemplo n.º 2
0
/*
 * Hub interrupt.
 * This an indication that some port has changed status.
 * Notify the bus event handler thread that we need
 * to be explored again.
 */
void
uhub_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status)
{
	struct uhub_softc *sc = addr;

	DPRINTFN(5,("uhub_intr: sc=%p\n", sc));
	if (status == USBD_STALLED)
		usbd_clear_endpoint_stall_async(sc->sc_ipipe);
	else if (status == USBD_NORMAL_COMPLETION)
		usb_needs_explore(sc->sc_hub);
}
/*------------------------------------------------------------------------*
 *	usb_handle_request_callback
 *
 * This function is the USB callback for generic USB Device control
 * transfers.
 *------------------------------------------------------------------------*/
void
usb_handle_request_callback(struct usb_xfer *xfer, usb_error_t error)
{
	usb_error_t err;

	/* check the current transfer state */

	switch (USB_GET_STATE(xfer)) {
	case USB_ST_SETUP:
	case USB_ST_TRANSFERRED:

		/* handle the request */
		err = usb_handle_request(xfer);

		if (err) {

			if (err == USB_ERR_BAD_CONTEXT) {
				/* we need to re-setup the control transfer */
				usb_needs_explore(xfer->xroot->bus, 0);
				break;
			}
			goto tr_restart;
		}
		usbd_transfer_submit(xfer);
		break;

	default:
		/* check if a control transfer is active */
		if (xfer->flags_int.control_rem != 0xFFFF) {
			/* handle the request */
			err = usb_handle_request(xfer);
		}
		if (xfer->error != USB_ERR_CANCELLED) {
			/* should not happen - try stalling */
			goto tr_restart;
		}
		break;
	}
	return;

tr_restart:
	/*
	 * If a control transfer is active, stall it, and wait for the
	 * next control transfer.
	 */
	usbd_xfer_set_frame_len(xfer, 0, sizeof(struct usb_device_request));
	xfer->nframes = 1;
	xfer->flags.manual_status = 1;
	xfer->flags.force_short_xfer = 0;
	usbd_xfer_set_stall(xfer);	/* cancel previous transfer, if any */
	usbd_transfer_submit(xfer);
}
Exemplo n.º 4
0
/*
 * This is an indication that some port has changed status.  Remember
 * the ports that need attention and notify the USB task thread that
 * we need to be explored again.
 */
void
uhub_intr(struct usbd_xfer *xfer, void *addr, usbd_status status)
{
	struct uhub_softc *sc = addr;
	uint32_t stats = 0;
	int i;

	if (usbd_is_dying(sc->sc_hub))
		return;

	DPRINTF("%s: intr status=%d\n", sc->sc_dev.dv_xname, status);

	if (status == USBD_STALLED)
		usbd_clear_endpoint_stall_async(sc->sc_ipipe);
	else if (status == USBD_NORMAL_COMPLETION) {
		for (i = 0; i < xfer->actlen; i++)
			stats |= (uint32_t)(xfer->buffer[i]) << (i * 8);
		sc->sc_status |= stats;

		usb_needs_explore(sc->sc_hub, 0);
	}
}
Exemplo n.º 5
0
/*------------------------------------------------------------------------*
 *	usb_attach_sub
 *
 * This function creates a thread which runs the USB attach code.
 *------------------------------------------------------------------------*/
static void
usb_attach_sub(device_t dev, struct usb_bus *bus)
{
	mtx_lock(&Giant);
	if (usb_devclass_ptr == NULL)
		usb_devclass_ptr = devclass_find("usbus");
	mtx_unlock(&Giant);

#if USB_HAVE_PF
	usbpf_attach(bus);
#endif
	/* Initialise USB process messages */
	bus->explore_msg[0].hdr.pm_callback = &usb_bus_explore;
	bus->explore_msg[0].bus = bus;
	bus->explore_msg[1].hdr.pm_callback = &usb_bus_explore;
	bus->explore_msg[1].bus = bus;

	bus->detach_msg[0].hdr.pm_callback = &usb_bus_detach;
	bus->detach_msg[0].bus = bus;
	bus->detach_msg[1].hdr.pm_callback = &usb_bus_detach;
	bus->detach_msg[1].bus = bus;

	bus->attach_msg[0].hdr.pm_callback = &usb_bus_attach;
	bus->attach_msg[0].bus = bus;
	bus->attach_msg[1].hdr.pm_callback = &usb_bus_attach;
	bus->attach_msg[1].bus = bus;

	bus->suspend_msg[0].hdr.pm_callback = &usb_bus_suspend;
	bus->suspend_msg[0].bus = bus;
	bus->suspend_msg[1].hdr.pm_callback = &usb_bus_suspend;
	bus->suspend_msg[1].bus = bus;

	bus->resume_msg[0].hdr.pm_callback = &usb_bus_resume;
	bus->resume_msg[0].bus = bus;
	bus->resume_msg[1].hdr.pm_callback = &usb_bus_resume;
	bus->resume_msg[1].bus = bus;

	bus->reset_msg[0].hdr.pm_callback = &usb_bus_reset;
	bus->reset_msg[0].bus = bus;
	bus->reset_msg[1].hdr.pm_callback = &usb_bus_reset;
	bus->reset_msg[1].bus = bus;

	bus->shutdown_msg[0].hdr.pm_callback = &usb_bus_shutdown;
	bus->shutdown_msg[0].bus = bus;
	bus->shutdown_msg[1].hdr.pm_callback = &usb_bus_shutdown;
	bus->shutdown_msg[1].bus = bus;

#if USB_HAVE_PER_BUS_PROCESS
	/* Create USB explore and callback processes */

	if (usb_proc_create(USB_BUS_GIANT_PROC(bus),
	    &bus->bus_mtx, device_get_nameunit(dev), USB_PRI_MED)) {
		device_printf(dev, "WARNING: Creation of USB Giant "
		    "callback process failed.\n");
	} else if (usb_proc_create(USB_BUS_NON_GIANT_PROC(bus),
	    &bus->bus_mtx, device_get_nameunit(dev), USB_PRI_HIGH)) {
		device_printf(dev, "WARNING: Creation of USB non-Giant "
		    "callback process failed.\n");
	} else if (usb_proc_create(USB_BUS_EXPLORE_PROC(bus),
	    &bus->bus_mtx, device_get_nameunit(dev), USB_PRI_MED)) {
		device_printf(dev, "WARNING: Creation of USB explore "
		    "process failed.\n");
	} else if (usb_proc_create(USB_BUS_CONTROL_XFER_PROC(bus),
	    &bus->bus_mtx, device_get_nameunit(dev), USB_PRI_MED)) {
		device_printf(dev, "WARNING: Creation of USB control transfer "
		    "process failed.\n");
	} else
#endif
	{
		/* Get final attach going */
		USB_BUS_LOCK(bus);
		usb_proc_msignal(USB_BUS_EXPLORE_PROC(bus),
		    &bus->attach_msg[0], &bus->attach_msg[1]);
		USB_BUS_UNLOCK(bus);

		/* Do initial explore */
		usb_needs_explore(bus, 1);
	}
}