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

📄 dummy_hcd.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
			total = transfer (dum, urb, ep, limit);			break;		}		/* incomplete transfer? */		if (urb->status == -EINPROGRESS)			continue;return_urb:		urb->hcpriv = NULL;		list_del (&urbp->urbp_list);		kfree (urbp);		if (ep)			ep->already_seen = ep->setup_stage = 0;		spin_unlock (&dum->lock);		usb_hcd_giveback_urb (dummy_to_hcd(dum), urb, NULL);		spin_lock (&dum->lock);		goto restart;	}	if (list_empty (&dum->urbp_list)) {		usb_put_dev (dum->udev);		dum->udev = NULL;	} else if (dum->rh_state == DUMMY_RH_RUNNING) {		/* want a 1 msec delay here */		mod_timer (&dum->timer, jiffies + msecs_to_jiffies(1));	}	spin_unlock_irqrestore (&dum->lock, flags);}/*-------------------------------------------------------------------------*/#define PORT_C_MASK \	((USB_PORT_STAT_C_CONNECTION \	| USB_PORT_STAT_C_ENABLE \	| USB_PORT_STAT_C_SUSPEND \	| USB_PORT_STAT_C_OVERCURRENT \	| USB_PORT_STAT_C_RESET) << 16)static int dummy_hub_status (struct usb_hcd *hcd, char *buf){	struct dummy		*dum;	unsigned long		flags;	int			retval = 0;	dum = hcd_to_dummy (hcd);	spin_lock_irqsave (&dum->lock, flags);	if (hcd->state != HC_STATE_RUNNING)		goto done;	if (dum->resuming && time_after_eq (jiffies, dum->re_timeout)) {		dum->port_status |= (USB_PORT_STAT_C_SUSPEND << 16);		dum->port_status &= ~USB_PORT_STAT_SUSPEND;		set_link_state (dum);	}	if ((dum->port_status & PORT_C_MASK) != 0) {		*buf = (1 << 1);		dev_dbg (dummy_dev(dum), "port status 0x%08x has changes\n",				dum->port_status);		retval = 1;		if (dum->rh_state == DUMMY_RH_SUSPENDED)			usb_hcd_resume_root_hub (hcd);	}done:	spin_unlock_irqrestore (&dum->lock, flags);	return retval;}static inline voidhub_descriptor (struct usb_hub_descriptor *desc){	memset (desc, 0, sizeof *desc);	desc->bDescriptorType = 0x29;	desc->bDescLength = 9;	desc->wHubCharacteristics = (__force __u16)			(__constant_cpu_to_le16 (0x0001));	desc->bNbrPorts = 1;	desc->bitmap [0] = 0xff;	desc->bitmap [1] = 0xff;}static int dummy_hub_control (	struct usb_hcd	*hcd,	u16		typeReq,	u16		wValue,	u16		wIndex,	char		*buf,	u16		wLength) {	struct dummy	*dum;	int		retval = 0;	unsigned long	flags;	if (hcd->state != HC_STATE_RUNNING)		return -ETIMEDOUT;	dum = hcd_to_dummy (hcd);	spin_lock_irqsave (&dum->lock, flags);	switch (typeReq) {	case ClearHubFeature:		break;	case ClearPortFeature:		switch (wValue) {		case USB_PORT_FEAT_SUSPEND:			if (dum->port_status & USB_PORT_STAT_SUSPEND) {				/* 20msec resume signaling */				dum->resuming = 1;				dum->re_timeout = jiffies +						msecs_to_jiffies(20);			}			break;		case USB_PORT_FEAT_POWER:			if (dum->port_status & USB_PORT_STAT_POWER)				dev_dbg (dummy_dev(dum), "power-off\n");			/* FALLS THROUGH */		default:			dum->port_status &= ~(1 << wValue);			set_link_state (dum);		}		break;	case GetHubDescriptor:		hub_descriptor ((struct usb_hub_descriptor *) buf);		break;	case GetHubStatus:		*(__le32 *) buf = __constant_cpu_to_le32 (0);		break;	case GetPortStatus:		if (wIndex != 1)			retval = -EPIPE;		/* whoever resets or resumes must GetPortStatus to		 * complete it!!		 */		if (dum->resuming &&				time_after_eq (jiffies, dum->re_timeout)) {			dum->port_status |= (USB_PORT_STAT_C_SUSPEND << 16);			dum->port_status &= ~USB_PORT_STAT_SUSPEND;		}		if ((dum->port_status & USB_PORT_STAT_RESET) != 0 &&				time_after_eq (jiffies, dum->re_timeout)) {			dum->port_status |= (USB_PORT_STAT_C_RESET << 16);			dum->port_status &= ~USB_PORT_STAT_RESET;			if (dum->pullup) {				dum->port_status |= USB_PORT_STAT_ENABLE;				/* give it the best speed we agree on */				dum->gadget.speed = dum->driver->speed;				dum->gadget.ep0->maxpacket = 64;				switch (dum->gadget.speed) {				case USB_SPEED_HIGH:					dum->port_status |=						USB_PORT_STAT_HIGH_SPEED;					break;				case USB_SPEED_LOW:					dum->gadget.ep0->maxpacket = 8;					dum->port_status |=						USB_PORT_STAT_LOW_SPEED;					break;				default:					dum->gadget.speed = USB_SPEED_FULL;					break;				}			}		}		set_link_state (dum);		((__le16 *) buf)[0] = cpu_to_le16 (dum->port_status);		((__le16 *) buf)[1] = cpu_to_le16 (dum->port_status >> 16);		break;	case SetHubFeature:		retval = -EPIPE;		break;	case SetPortFeature:		switch (wValue) {		case USB_PORT_FEAT_SUSPEND:			if (dum->active) {				dum->port_status |= USB_PORT_STAT_SUSPEND;				/* HNP would happen here; for now we				 * assume b_bus_req is always true.				 */				set_link_state (dum);				if (((1 << USB_DEVICE_B_HNP_ENABLE)						& dum->devstatus) != 0)					dev_dbg (dummy_dev(dum),							"no HNP yet!\n");			}			break;		case USB_PORT_FEAT_POWER:			dum->port_status |= USB_PORT_STAT_POWER;			set_link_state (dum);			break;		case USB_PORT_FEAT_RESET:			/* if it's already enabled, disable */			dum->port_status &= ~(USB_PORT_STAT_ENABLE					| USB_PORT_STAT_LOW_SPEED					| USB_PORT_STAT_HIGH_SPEED);			dum->devstatus = 0;			/* 50msec reset signaling */			dum->re_timeout = jiffies + msecs_to_jiffies(50);			/* FALLS THROUGH */		default:			if ((dum->port_status & USB_PORT_STAT_POWER) != 0) {				dum->port_status |= (1 << wValue);				set_link_state (dum);			}		}		break;	default:		dev_dbg (dummy_dev(dum),			"hub control req%04x v%04x i%04x l%d\n",			typeReq, wValue, wIndex, wLength);		/* "protocol stall" on error */		retval = -EPIPE;	}	spin_unlock_irqrestore (&dum->lock, flags);	if ((dum->port_status & PORT_C_MASK) != 0)		usb_hcd_poll_rh_status (hcd);	return retval;}static int dummy_bus_suspend (struct usb_hcd *hcd){	struct dummy *dum = hcd_to_dummy (hcd);	spin_lock_irq (&dum->lock);	dum->rh_state = DUMMY_RH_SUSPENDED;	set_link_state (dum);	spin_unlock_irq (&dum->lock);	return 0;}static int dummy_bus_resume (struct usb_hcd *hcd){	struct dummy *dum = hcd_to_dummy (hcd);	spin_lock_irq (&dum->lock);	dum->rh_state = DUMMY_RH_RUNNING;	set_link_state (dum);	if (!list_empty(&dum->urbp_list))		mod_timer (&dum->timer, jiffies);	spin_unlock_irq (&dum->lock);	return 0;}/*-------------------------------------------------------------------------*/static inline ssize_tshow_urb (char *buf, size_t size, struct urb *urb){	int ep = usb_pipeendpoint (urb->pipe);	return snprintf (buf, size,		"urb/%p %s ep%d%s%s len %d/%d\n",		urb,		({ char *s;		 switch (urb->dev->speed) {		 case USB_SPEED_LOW:	s = "ls"; break;		 case USB_SPEED_FULL:	s = "fs"; break;		 case USB_SPEED_HIGH:	s = "hs"; break;		 default:		s = "?"; break;		 }; s; }),		ep, ep ? (usb_pipein (urb->pipe) ? "in" : "out") : "",		({ char *s; \		 switch (usb_pipetype (urb->pipe)) { \		 case PIPE_CONTROL:	s = ""; break; \		 case PIPE_BULK:	s = "-bulk"; break; \		 case PIPE_INTERRUPT:	s = "-int"; break; \		 default: 		s = "-iso"; break; \		}; s;}),		urb->actual_length, urb->transfer_buffer_length);}static ssize_tshow_urbs (struct device *dev, struct device_attribute *attr, char *buf){	struct usb_hcd		*hcd = dev_get_drvdata (dev);	struct dummy		*dum = hcd_to_dummy (hcd);	struct urbp		*urbp;	size_t			size = 0;	unsigned long		flags;	spin_lock_irqsave (&dum->lock, flags);	list_for_each_entry (urbp, &dum->urbp_list, urbp_list) {		size_t		temp;		temp = show_urb (buf, PAGE_SIZE - size, urbp->urb);		buf += temp;		size += temp;	}	spin_unlock_irqrestore (&dum->lock, flags);	return size;}static DEVICE_ATTR (urbs, S_IRUGO, show_urbs, NULL);static int dummy_start (struct usb_hcd *hcd){	struct dummy		*dum;	dum = hcd_to_dummy (hcd);	/*	 * MASTER side init ... we emulate a root hub that'll only ever	 * talk to one device (the slave side).  Also appears in sysfs,	 * just like more familiar pci-based HCDs.	 */	spin_lock_init (&dum->lock);	init_timer (&dum->timer);	dum->timer.function = dummy_timer;	dum->timer.data = (unsigned long) dum;	dum->rh_state = DUMMY_RH_RUNNING;	INIT_LIST_HEAD (&dum->urbp_list);	/* only show a low-power port: just 8mA */	hcd->power_budget = 8;	hcd->state = HC_STATE_RUNNING;	hcd->uses_new_polling = 1;#ifdef CONFIG_USB_OTG	hcd->self.otg_port = 1;#endif	/* FIXME 'urbs' should be a per-device thing, maybe in usbcore */	device_create_file (dummy_dev(dum), &dev_attr_urbs);	return 0;}static void dummy_stop (struct usb_hcd *hcd){	struct dummy		*dum;	dum = hcd_to_dummy (hcd);	device_remove_file (dummy_dev(dum), &dev_attr_urbs);	usb_gadget_unregister_driver (dum->driver);	dev_info (dummy_dev(dum), "stopped\n");}/*-------------------------------------------------------------------------*/static int dummy_h_get_frame (struct usb_hcd *hcd){	return dummy_g_get_frame (NULL);}static const struct hc_driver dummy_hcd = {	.description =		(char *) driver_name,	.product_desc =		"Dummy host controller",	.hcd_priv_size =	sizeof(struct dummy),	.flags =		HCD_USB2,	.start =		dummy_start,	.stop =			dummy_stop,	.urb_enqueue = 		dummy_urb_enqueue,	.urb_dequeue = 		dummy_urb_dequeue,	.get_frame_number = 	dummy_h_get_frame,	.hub_status_data = 	dummy_hub_status,	.hub_control = 		dummy_hub_control,	.bus_suspend =		dummy_bus_suspend,	.bus_resume =		dummy_bus_resume,};static int dummy_hcd_probe (struct platform_device *dev){	struct usb_hcd		*hcd;	int			retval;	dev_info(&dev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);	hcd = usb_create_hcd (&dummy_hcd, &dev->dev, dev->dev.bus_id);	if (!hcd)		return -ENOMEM;	the_controller = hcd_to_dummy (hcd);	retval = usb_add_hcd(hcd, 0, 0);	if (retval != 0) {		usb_put_hcd (hcd);		the_controller = NULL;	}	return retval;}static int dummy_hcd_remove (struct platform_device *dev){	struct usb_hcd		*hcd;	hcd = platform_get_drvdata (dev);	usb_remove_hcd (hcd);	usb_put_hcd (hcd);	the_controller = NULL;	return 0;}static int dummy_hcd_suspend (struct platform_device *dev, pm_message_t state){	struct usb_hcd		*hcd;	dev_dbg (&dev->dev, "%s\n", __FUNCTION__);	hcd = platform_get_drvdata (dev);	hcd->state = HC_STATE_SUSPENDED;	return 0;}static int dummy_hcd_resume (struct platform_device *dev){	struct usb_hcd		*hcd;	dev_dbg (&dev->dev, "%s\n", __FUNCTION__);	hcd = platform_get_drvdata (dev);	hcd->state = HC_STATE_RUNNING;	usb_hcd_poll_rh_status (hcd);	return 0;}static struct platform_driver dummy_hcd_driver = {	.probe		= dummy_hcd_probe,	.remove		= dummy_hcd_remove,	.suspend	= dummy_hcd_suspend,	.resume		= dummy_hcd_resume,	.driver		= {		.name	= (char *) driver_name,		.owner	= THIS_MODULE,	},};/*-------------------------------------------------------------------------*//* These don't need to do anything because the pdev structures are * statically allocated. */static voiddummy_udc_release (struct device *dev) {}static voiddummy_hcd_release (struct device *dev) {}static struct platform_device		the_udc_pdev = {	.name		= (char *) gadget_name,	.id		= -1,	.dev		= {		.release	= dummy_udc_release,	},};static struct platform_device		the_hcd_pdev = {	.name		= (char *) driver_name,	.id		= -1,	.dev		= {		.release	= dummy_hcd_release,	},};static int __init init (void){	int	retval;	if (usb_disabled ())		return -ENODEV;	retval = platform_driver_register (&dummy_hcd_driver);	if (retval < 0)		return retval;	retval = platform_driver_register (&dummy_udc_driver);	if (retval < 0)		goto err_register_udc_driver;	retval = platform_device_register (&the_hcd_pdev);	if (retval < 0)		goto err_register_hcd;	retval = platform_device_register (&the_udc_pdev);	if (retval < 0)		goto err_register_udc;	return retval;err_register_udc:	platform_device_unregister (&the_hcd_pdev);err_register_hcd:	platform_driver_unregister (&dummy_udc_driver);err_register_udc_driver:	platform_driver_unregister (&dummy_hcd_driver);	return retval;}module_init (init);static void __exit cleanup (void){	platform_device_unregister (&the_udc_pdev);	platform_device_unregister (&the_hcd_pdev);	platform_driver_unregister (&dummy_udc_driver);	platform_driver_unregister (&dummy_hcd_driver);}module_exit (cleanup);

⌨️ 快捷键说明

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