uhub.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 528 行 · 第 1/2 页

C
528
字号
/*	$NetBSD: uhub.c,v 1.16 1999/01/10 19:13:15 augustss Exp $	*//*	$FreeBSD: src/sys/dev/usb/uhub.c,v 1.7.2.1 1999/05/08 23:04:49 n_hibma Exp $	*//* * Copyright (c) 1998 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Lennart Augustsson (augustss@carlstedt.se) at * Carlstedt Research & Technology. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *        This product includes software developed by the NetBSD *        Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its *    contributors may be used to endorse or promote products derived *    from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. *//* * USB spec: http://www.usb.org/cgi-usb/mailmerge.cgi/home/usb/docs/developers/cgiform.tpl */#include <sys/param.h>#include <sys/systm.h>#include <sys/kernel.h>#include <sys/malloc.h>#if defined(__NetBSD__)#include <sys/device.h>#elif defined(__FreeBSD__)#include <sys/module.h>#include <sys/bus.h>#endif#include <sys/proc.h>#include <dev/usb/usb.h>#include <dev/usb/usbdi.h>#include <dev/usb/usbdi_util.h>#include <dev/usb/usbdivar.h>#ifdef UHUB_DEBUG#define DPRINTF(x)	if (usbdebug) logprintf x#define DPRINTFN(n,x)	if (usbdebug>(n)) logprintf xextern int	usbdebug;#else#define DPRINTF(x)#define DPRINTFN(n,x)#endifstruct uhub_softc {	bdevice			sc_dev;		/* base device */	usbd_device_handle	sc_hub;		/* USB device */	usbd_pipe_handle	sc_ipipe;	/* interrupt pipe */	u_int8_t		sc_status[1];	/* XXX more ports */	u_char			sc_running;};usbd_status uhub_init_port __P((struct usbd_port *));void uhub_disconnect_port __P((struct usbd_port *up));usbd_status uhub_explore __P((usbd_device_handle hub));void uhub_intr __P((usbd_request_handle, usbd_private_handle, usbd_status));/* void uhub_disco __P((void *)); */USB_DECLARE_DRIVER(uhub);#if defined(__FreeBSD__)devclass_t uhubroot_devclass;static device_method_t uhubroot_methods[] = {        DEVMETHOD(device_probe, uhub_match),        DEVMETHOD(device_attach, uhub_attach),	/* detach is not allowed for a root hub */        {0,0}};static driver_t uhubroot_driver = {        "uhub",        uhubroot_methods,        DRIVER_TYPE_MISC,        sizeof(struct uhub_softc)};#endif#if defined(__NetBSD__)struct cfattach uhub_uhub_ca = {	sizeof(struct uhub_softc), uhub_match, uhub_attach};#endifUSB_MATCH(uhub){	USB_MATCH_START(uhub, uaa);	usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device);		DPRINTFN(5,("uhub_match, dd=%p\n", dd));	/* 	 * The subclass for hubs seems to be 0 for some and 1 for others,	 * so we just ignore the subclass.	 */	if (uaa->iface == 0 && dd->bDeviceClass == UCLASS_HUB)		return (UMATCH_DEVCLASS_DEVSUBCLASS);	return (UMATCH_NONE);}USB_ATTACH(uhub){	USB_ATTACH_START(uhub, sc, uaa);	usbd_device_handle dev = uaa->device;	char devinfo[1024];	usbd_status r;	struct usbd_hub *hub;	usb_device_request_t req;	usb_hub_descriptor_t hubdesc;	int p, port, nports, nremov;	usbd_interface_handle iface;	usb_endpoint_descriptor_t *ed;		DPRINTFN(1,("uhub_attach\n"));	sc->sc_hub = dev;	usbd_devinfo(dev, 1, devinfo);	USB_ATTACH_SETUP;	printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);	r = usbd_set_config_index(dev, 0, 1);	if (r != USBD_NORMAL_COMPLETION) {		DPRINTF(("%s: configuration failed, %s\n",			 USBDEVNAME(sc->sc_dev), usbd_errstr(r)));		USB_ATTACH_ERROR_RETURN;	}	if (dev->depth > USB_HUB_MAX_DEPTH) {		printf("%s: hub depth (%d) exceeded, hub ignored\n",		       USBDEVNAME(sc->sc_dev), USB_HUB_MAX_DEPTH);		USB_ATTACH_ERROR_RETURN;	}	/* Get hub descriptor. */	req.bmRequestType = UT_READ_CLASS_DEVICE;	req.bRequest = UR_GET_DESCRIPTOR;	USETW(req.wValue, 0);	USETW(req.wIndex, 0);	USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE);	DPRINTFN(1,("usb_init_hub: getting hub descriptor\n"));	r = usbd_do_request(dev, &req, &hubdesc);	nports = hubdesc.bNbrPorts;	if (r == USBD_NORMAL_COMPLETION && nports > 7) {		USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE + (nports+1) / 8);		r = usbd_do_request(dev, &req, &hubdesc);	}	if (r != USBD_NORMAL_COMPLETION) {		DPRINTF(("%s: getting hub descriptor failed, %s\n",			 USBDEVNAME(sc->sc_dev), usbd_errstr(r)));		USB_ATTACH_ERROR_RETURN;	}	for (nremov = 0, port = 1; port <= nports; port++)		if (!UHD_NOT_REMOV(&hubdesc, port))			nremov++;	printf("%s: %d port%s with %d removable, %s powered\n",	       USBDEVNAME(sc->sc_dev), nports, nports != 1 ? "s" : "",	       nremov, dev->self_powered ? "self" : "bus");		hub = malloc(sizeof(*hub) + (nports-1) * sizeof(struct usbd_port),		     M_USB, M_NOWAIT);	if (hub == 0)		USB_ATTACH_ERROR_RETURN;	dev->hub = hub;	dev->hub->hubsoftc = sc;	hub->explore = uhub_explore;	hub->hubdesc = hubdesc;		DPRINTFN(1,("usbhub_init_hub: selfpowered=%d, parent=%p, "		    "parent->selfpowered=%d\n",		 dev->self_powered, dev->powersrc->parent,		 dev->powersrc->parent ? 		 dev->powersrc->parent->self_powered : 0));	if (!dev->self_powered && dev->powersrc->parent &&	    !dev->powersrc->parent->self_powered) {		printf("%s: bus powered hub connected to bus powered hub, "		       "ignored\n",		       USBDEVNAME(sc->sc_dev));		USB_ATTACH_ERROR_RETURN;	}	/* Set up interrupt pipe. */	r = usbd_device2interface_handle(dev, 0, &iface);	if (r != USBD_NORMAL_COMPLETION) {		printf("%s: no interface handle\n", USBDEVNAME(sc->sc_dev));		USB_ATTACH_ERROR_RETURN;	}	ed = usbd_interface2endpoint_descriptor(iface, 0);	if (ed == 0) {		printf("%s: no endpoint descriptor\n", USBDEVNAME(sc->sc_dev));		USB_ATTACH_ERROR_RETURN;	}	if ((ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) {		printf("%s: bad interrupt endpoint\n", USBDEVNAME(sc->sc_dev));		USB_ATTACH_ERROR_RETURN;	}	r = usbd_open_pipe_intr(iface, ed->bEndpointAddress,USBD_SHORT_XFER_OK,				&sc->sc_ipipe, sc, sc->sc_status, 				sizeof(sc->sc_status),				uhub_intr);	if (r != USBD_NORMAL_COMPLETION) {		printf("%s: cannot open interrupt pipe\n", 		       USBDEVNAME(sc->sc_dev));		USB_ATTACH_ERROR_RETURN;	}	/* Wait with power off for a while. */	usbd_delay_ms(dev, USB_POWER_DOWN_TIME);	for (p = 0; p < nports; p++) {		struct usbd_port *up = &hub->ports[p];		up->device = 0;		up->parent = dev;		up->portno = p+1;		r = uhub_init_port(up);		if (r != USBD_NORMAL_COMPLETION)			printf("%s: init of port %d failed\n", 			       USBDEVNAME(sc->sc_dev), up->portno);	}	sc->sc_running = 1;	USB_ATTACH_SUCCESS_RETURN;}#if defined(__FreeBSD__)static intuhub_detach(device_t self){	struct uhub_softc *sc = device_get_softc(self);	DPRINTF(("%s: disconnected\n", USBDEVNAME(self)));	free(sc->sc_hub->hub, M_USB);	return 0;}#endifusbd_status

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?