⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hcd.c

📁 h内核
💻 C
📖 第 1 页 / 共 4 页
字号:
				ubuf, wLength);			break;		default:			goto error;		}		break;	case DeviceRequest | USB_REQ_GET_INTERFACE:		ubuf [0] = 0;			/* FALLTHROUGH */	case DeviceOutRequest | USB_REQ_SET_INTERFACE:		break;	case DeviceOutRequest | USB_REQ_SET_ADDRESS:		// wValue == urb->dev->devaddr		dev_dbg (hcd->self.controller, "root hub device address %d\n",			wValue);		break;	/* INTERFACE REQUESTS (no defined feature/status flags) */	/* ENDPOINT REQUESTS */	case EndpointRequest | USB_REQ_GET_STATUS:		// ENDPOINT_HALT flag		ubuf [0] = 0;		ubuf [1] = 0;			/* FALLTHROUGH */	case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:	case EndpointOutRequest | USB_REQ_SET_FEATURE:		dev_dbg (hcd->self.controller, "no endpoint features yet\n");		break;	/* CLASS REQUESTS (and errors) */	default:		/* non-generic request */		if (HCD_IS_SUSPENDED (hcd->state))			urb->status = -EAGAIN;		else			urb->status = hcd->driver->hub_control (hcd,				typeReq, wValue, wIndex,				ubuf, wLength);		break;error:		/* "protocol stall" on error */		urb->status = -EPIPE;	}	if (urb->status) {		urb->actual_length = 0;		if (urb->status != -EPIPE) {			dev_dbg (hcd->self.controller,				"CTRL: TypeReq=0x%x val=0x%x "				"idx=0x%x len=%d ==> %d\n",				typeReq, wValue, wIndex,				wLength, urb->status);		}	}	if (bufp) {		if (urb->transfer_buffer_length < len)			len = urb->transfer_buffer_length;		urb->actual_length = len;		// always USB_DIR_IN, toward host		memcpy (ubuf, bufp, len);		/* report whether RH hardware supports remote wakeup */		if (patch_wakeup)			((struct usb_config_descriptor *)ubuf)->bmAttributes				|= USB_CONFIG_ATT_WAKEUP;	}	/* any errors get returned through the urb completion */	local_irq_save (flags);	usb_hcd_giveback_urb (hcd, urb, NULL);	local_irq_restore (flags);	return 0;}/*-------------------------------------------------------------------------*//* * Root Hub interrupt transfers are synthesized with a timer. * Completions are called in_interrupt() but not in_irq(). * * Note: some root hubs (including common UHCI based designs) can't * correctly issue port change IRQs.  They're the ones that _need_ a * timer; most other root hubs don't.  Some systems could save a * lot of battery power by eliminating these root hub timer IRQs. */static void rh_report_status (unsigned long ptr);static int rh_status_urb (struct usb_hcd *hcd, struct urb *urb) {	int	len = 1 + (urb->dev->maxchild / 8);	/* rh_timer protected by hcd_data_lock */	if (hcd->rh_timer.data || urb->transfer_buffer_length < len) {		dev_dbg (hcd->self.controller,				"not queuing rh status urb, stat %d\n",				urb->status);		return -EINVAL;	}	init_timer (&hcd->rh_timer);	hcd->rh_timer.function = rh_report_status;	hcd->rh_timer.data = (unsigned long) urb;	/* USB 2.0 spec says 256msec; this is close enough */	hcd->rh_timer.expires = jiffies + HZ/4;	add_timer (&hcd->rh_timer);	urb->hcpriv = hcd;	/* nonzero to indicate it's queued */	return 0;}/* timer callback */static void rh_report_status (unsigned long ptr){	struct urb	*urb;	struct usb_hcd	*hcd;	int		length = 0;	unsigned long	flags;	urb = (struct urb *) ptr;	local_irq_save (flags);	spin_lock (&urb->lock);	/* do nothing if the urb's been unlinked */	if (!urb->dev			|| urb->status != -EINPROGRESS			|| (hcd = urb->dev->bus->hcpriv) == NULL) {		spin_unlock (&urb->lock);		local_irq_restore (flags);		return;	}	/* complete the status urb, or retrigger the timer */	spin_lock (&hcd_data_lock);	if (urb->dev->state == USB_STATE_CONFIGURED) {		length = hcd->driver->hub_status_data (					hcd, urb->transfer_buffer);		if (length > 0) {			hcd->rh_timer.data = 0;			urb->actual_length = length;			urb->status = 0;			urb->hcpriv = NULL;		} else			mod_timer (&hcd->rh_timer, jiffies + HZ/4);	}	spin_unlock (&hcd_data_lock);	spin_unlock (&urb->lock);	/* local irqs are always blocked in completions */	if (length > 0)		usb_hcd_giveback_urb (hcd, urb, NULL);	local_irq_restore (flags);}/*-------------------------------------------------------------------------*/static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb){	if (usb_pipeint (urb->pipe)) {		int		retval;		unsigned long	flags;		spin_lock_irqsave (&hcd_data_lock, flags);		retval = rh_status_urb (hcd, urb);		spin_unlock_irqrestore (&hcd_data_lock, flags);		return retval;	}	if (usb_pipecontrol (urb->pipe))		return rh_call_control (hcd, urb);	else		return -EINVAL;}/*-------------------------------------------------------------------------*/static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb){	unsigned long	flags;	/* note:  always a synchronous unlink */	if ((unsigned long) urb == hcd->rh_timer.data) {		del_timer_sync (&hcd->rh_timer);		hcd->rh_timer.data = 0;		local_irq_save (flags);		urb->hcpriv = NULL;		usb_hcd_giveback_urb (hcd, urb, NULL);		local_irq_restore (flags);	} else if (usb_pipeendpoint(urb->pipe) == 0) {		spin_lock_irq(&urb->lock);	/* from usb_kill_urb */		++urb->reject;		spin_unlock_irq(&urb->lock);		wait_event(usb_kill_urb_queue,				atomic_read(&urb->use_count) == 0);		spin_lock_irq(&urb->lock);		--urb->reject;		spin_unlock_irq(&urb->lock);	} else		return -EINVAL;	return 0;}/*-------------------------------------------------------------------------*//* exported only within usbcore */struct usb_bus *usb_bus_get (struct usb_bus *bus){	struct class_device *tmp;	if (!bus)		return NULL;	tmp = class_device_get(&bus->class_dev);	if (tmp)        		return to_usb_bus(tmp);	else		return NULL;}/* exported only within usbcore */void usb_bus_put (struct usb_bus *bus){	if (bus)		class_device_put(&bus->class_dev);}/*-------------------------------------------------------------------------*/static void usb_host_release(struct class_device *class_dev){	struct usb_bus *bus = to_usb_bus(class_dev);	if (bus->release)		bus->release(bus);}static struct class usb_host_class = {	.name		= "usb_host",	.release	= &usb_host_release,};int usb_host_init(void){	return class_register(&usb_host_class);}void usb_host_cleanup(void){	class_unregister(&usb_host_class);}/** * usb_bus_init - shared initialization code * @bus: the bus structure being initialized * * This code is used to initialize a usb_bus structure, memory for which is * separately managed. */void usb_bus_init (struct usb_bus *bus){	memset (&bus->devmap, 0, sizeof(struct usb_devmap));	bus->devnum_next = 1;	bus->root_hub = NULL;	bus->hcpriv = NULL;	bus->busnum = -1;	bus->bandwidth_allocated = 0;	bus->bandwidth_int_reqs  = 0;	bus->bandwidth_isoc_reqs = 0;	INIT_LIST_HEAD (&bus->bus_list);	class_device_initialize(&bus->class_dev);	bus->class_dev.class = &usb_host_class;}EXPORT_SYMBOL (usb_bus_init);/** * usb_alloc_bus - creates a new USB host controller structure * @op: pointer to a struct usb_operations that this bus structure should use * Context: !in_interrupt() * * Creates a USB host controller bus structure with the specified  * usb_operations and initializes all the necessary internal objects. * * If no memory is available, NULL is returned. * * The caller should call usb_put_bus() when it is finished with the structure. */struct usb_bus *usb_alloc_bus (struct usb_operations *op){	struct usb_bus *bus;	bus = kmalloc (sizeof *bus, GFP_KERNEL);	if (!bus)		return NULL;	memset(bus, 0, sizeof(struct usb_bus));	usb_bus_init (bus);	bus->op = op;	return bus;}EXPORT_SYMBOL (usb_alloc_bus);/*-------------------------------------------------------------------------*//** * usb_register_bus - registers the USB host controller with the usb core * @bus: pointer to the bus to register * Context: !in_interrupt() * * Assigns a bus number, and links the controller into usbcore data * structures so that it can be seen by scanning the bus list. */int usb_register_bus(struct usb_bus *bus){	int busnum;	int retval;	down (&usb_bus_list_lock);	busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1);	if (busnum < USB_MAXBUS) {		set_bit (busnum, busmap.busmap);		bus->busnum = busnum;	} else {		printk (KERN_ERR "%s: too many buses\n", usbcore_name);		up(&usb_bus_list_lock);		return -E2BIG;	}	snprintf(bus->class_dev.class_id, BUS_ID_SIZE, "usb%d", busnum);	bus->class_dev.dev = bus->controller;	retval = class_device_add(&bus->class_dev);	if (retval) {		clear_bit(busnum, busmap.busmap);		up(&usb_bus_list_lock);		return retval;	}	/* Add it to the local list of buses */	list_add (&bus->bus_list, &usb_bus_list);	up (&usb_bus_list_lock);	usbfs_add_bus (bus);	dev_info (bus->controller, "new USB bus registered, assigned bus number %d\n", bus->busnum);	return 0;}EXPORT_SYMBOL (usb_register_bus);/** * usb_deregister_bus - deregisters the USB host controller * @bus: pointer to the bus to deregister * Context: !in_interrupt() * * Recycles the bus number, and unlinks the controller from usbcore data * structures so that it won't be seen by scanning the bus list. */void usb_deregister_bus (struct usb_bus *bus){	dev_info (bus->controller, "USB bus %d deregistered\n", bus->busnum);	/*	 * NOTE: make sure that all the devices are removed by the	 * controller code, as well as having it call this when cleaning	 * itself up	 */	down (&usb_bus_list_lock);	list_del (&bus->bus_list);	up (&usb_bus_list_lock);	usbfs_remove_bus (bus);	clear_bit (bus->busnum, busmap.busmap);	class_device_unregister(&bus->class_dev);}EXPORT_SYMBOL (usb_deregister_bus);/** * usb_register_root_hub - called by HCD to register its root hub  * @usb_dev: the usb root hub device to be registered. * @parent_dev: the parent device of this root hub. * * The USB host controller calls this function to register the root hub * properly with the USB subsystem.  It sets up the device properly in * the device tree and stores the root_hub pointer in the bus structure, * then calls usb_new_device() to register the usb device.  It also * assigns the root hub's USB address (always 1). */int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev){	const int devnum = 1;

⌨️ 快捷键说明

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