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

📄 dwc_otg_pcd.c

📁 host usb 主设备程序 支持sd卡 mouse keyboard 的最单单的驱动程序 gcc编译
💻 C
📖 第 1 页 / 共 4 页
字号:
	srp_timer->expires = jiffies + (HZ * 6);	add_timer(srp_timer);}/** * Tasklet * */extern void start_next_request(dwc_otg_pcd_ep_t * _ep);static void start_xfer_tasklet_func(unsigned long data){	dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data;	dwc_otg_core_if_t *core_if = pcd->otg_dev->core_if;	int i;	depctl_data_t diepctl;	DWC_DEBUGPL(DBG_PCDV, "Start xfer tasklet\n");	diepctl.d32 = dwc_read_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl);	if (pcd->ep0.queue_sof) {		pcd->ep0.queue_sof = 0;		start_next_request(&pcd->ep0);		// break;	}	for (i = 0; i < core_if->dev_if->num_in_eps; i++) {		depctl_data_t diepctl;		diepctl.d32 = dwc_read_reg32(&core_if->dev_if->in_ep_regs[i]->diepctl);		if (pcd->in_ep[i].queue_sof) {			pcd->in_ep[i].queue_sof = 0;			start_next_request(&pcd->in_ep[i]);			// break;		}	}	return;}static struct tasklet_struct start_xfer_tasklet = {	.next = NULL,	.state = 0,	.count = ATOMIC_INIT(0),	.func = start_xfer_tasklet_func,	.data = 0,};/** * This function initialized the pcd Dp structures to there default * state. * * @param _pcd the pcd structure. */void dwc_otg_pcd_reinit(dwc_otg_pcd_t * _pcd){	static const char *names[] = {		"ep0",		"ep1in",		"ep2in",		"ep3in",		"ep4in",		"ep5in",		"ep6in",		"ep7in",		"ep8in",		"ep9in",		"ep10in",		"ep11in",		"ep12in",		"ep13in",		"ep14in",		"ep15in",		"ep1out",		"ep2out",		"ep3out",		"ep4out",		"ep5out",		"ep6out",		"ep7out",		"ep8out",		"ep9out",		"ep10out",		"ep11out",		"ep12out",		"ep13out",		"ep14out",		"ep15out"	};	int i;	int in_ep_cntr, out_ep_cntr;	uint32_t hwcfg1;	uint32_t num_in_eps = (GET_CORE_IF(_pcd))->dev_if->num_in_eps;	uint32_t num_out_eps = (GET_CORE_IF(_pcd))->dev_if->num_out_eps;	dwc_otg_pcd_ep_t *ep;	DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _pcd);	INIT_LIST_HEAD(&_pcd->gadget.ep_list);	_pcd->gadget.ep0 = &_pcd->ep0.ep;	_pcd->gadget.speed = USB_SPEED_UNKNOWN;	INIT_LIST_HEAD(&_pcd->gadget.ep0->ep_list);	/**	 * Initialize the EP0 structure.	 */	ep = &_pcd->ep0;	/* Init EP structure */	ep->desc = 0;	ep->pcd = _pcd;	ep->stopped = 1;	/* Init DWC ep structure */	ep->dwc_ep.num = 0;	ep->dwc_ep.active = 0;	ep->dwc_ep.tx_fifo_num = 0;	/* Control until ep is actvated */	ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;	ep->dwc_ep.maxpacket = MAX_PACKET_SIZE;	ep->dwc_ep.dma_addr = 0;	ep->dwc_ep.start_xfer_buff = 0;	ep->dwc_ep.xfer_buff = 0;	ep->dwc_ep.xfer_len = 0;	ep->dwc_ep.xfer_count = 0;	ep->dwc_ep.sent_zlp = 0;	ep->dwc_ep.total_len = 0;	ep->queue_sof = 0;	/* Init the usb_ep structure. */	ep->ep.name = names[0];	ep->ep.ops = (struct usb_ep_ops *) &dwc_otg_pcd_ep_ops;	/**	 * @todo NGS: What should the max packet size be set to	 * here?  Before EP type is set?	 */	ep->ep.maxpacket = MAX_PACKET_SIZE;	list_add_tail(&ep->ep.ep_list, &_pcd->gadget.ep_list);	INIT_LIST_HEAD(&ep->queue);	/**	 * Initialize the EP structures.	 */	in_ep_cntr = 0;	hwcfg1 = (GET_CORE_IF(_pcd))->hwcfg1.d32 >> 3;	for (i = 1; in_ep_cntr < num_in_eps; i++) {		if ((hwcfg1 & 0x1) == 0) {			dwc_otg_pcd_ep_t *ep = &_pcd->in_ep[in_ep_cntr];			in_ep_cntr++;			/* Init EP structure */			ep->desc = 0;			ep->pcd = _pcd;			ep->stopped = 1;			/* Init DWC ep structure */			ep->dwc_ep.is_in = 1;			ep->dwc_ep.num = i;			ep->dwc_ep.active = 0;			ep->dwc_ep.tx_fifo_num = 0;			/* Control until ep is actvated */			ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;			ep->dwc_ep.maxpacket = MAX_PACKET_SIZE;			ep->dwc_ep.dma_addr = 0;			ep->dwc_ep.start_xfer_buff = 0;			ep->dwc_ep.xfer_buff = 0;			ep->dwc_ep.xfer_len = 0;			ep->dwc_ep.xfer_count = 0;			ep->dwc_ep.sent_zlp = 0;			ep->dwc_ep.total_len = 0;			ep->queue_sof = 0;			/* Init the usb_ep structure. */			/**			 * @todo NGS: Add direction to EP, based on contents			 * of HWCFG1.  Need a copy of HWCFG1 in pcd structure?			 * sprintf( ";r			 */			ep->ep.name = names[i];			ep->ep.ops = (struct usb_ep_ops *) &dwc_otg_pcd_ep_ops;			/**			 * @todo NGS: What should the max packet size be set to			 * here?  Before EP type is set?			 */			ep->ep.maxpacket = MAX_PACKET_SIZE;			list_add_tail(&ep->ep.ep_list, &_pcd->gadget.ep_list);			INIT_LIST_HEAD(&ep->queue);		}		hwcfg1 >>= 2;	}	out_ep_cntr = 0;	hwcfg1 = (GET_CORE_IF(_pcd))->hwcfg1.d32 >> 2;	for (i = 1; out_ep_cntr < num_out_eps; i++) {		if ((hwcfg1 & 0x1) == 0) {			dwc_otg_pcd_ep_t *ep = &_pcd->out_ep[out_ep_cntr];			out_ep_cntr++;			/* Init EP structure */			ep->desc = 0;			ep->pcd = _pcd;			ep->stopped = 1;			/* Init DWC ep structure */			ep->dwc_ep.is_in = 0;			ep->dwc_ep.num = i;			ep->dwc_ep.active = 0;			ep->dwc_ep.tx_fifo_num = 0;			/* Control until ep is actvated */			ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;			ep->dwc_ep.maxpacket = MAX_PACKET_SIZE;			ep->dwc_ep.dma_addr = 0;			ep->dwc_ep.start_xfer_buff = 0;			ep->dwc_ep.xfer_buff = 0;			ep->dwc_ep.xfer_len = 0;			ep->dwc_ep.xfer_count = 0;			ep->dwc_ep.sent_zlp = 0;			ep->dwc_ep.total_len = 0;			ep->queue_sof = 0;			/* Init the usb_ep structure. */			/**			 * @todo NGS: Add direction to EP, based on contents			 * of HWCFG1.  Need a copy of HWCFG1 in pcd structure?			 * sprintf( ";r			 */			ep->ep.name = names[15 + i];			ep->ep.ops = (struct usb_ep_ops *) &dwc_otg_pcd_ep_ops;			/**			 * @todo NGS: What should the max packet size be set to			 * here?  Before EP type is set?			 */			ep->ep.maxpacket = MAX_PACKET_SIZE;			list_add_tail(&ep->ep.ep_list, &_pcd->gadget.ep_list);			INIT_LIST_HEAD(&ep->queue);		}		hwcfg1 >>= 2;	}	/* remove ep0 from the list.  There is a ep0 pointer. */	list_del_init(&_pcd->ep0.ep.ep_list);	_pcd->ep0state = EP0_DISCONNECT;	_pcd->ep0.ep.maxpacket = MAX_EP0_SIZE;	_pcd->ep0.dwc_ep.maxpacket = MAX_EP0_SIZE;	_pcd->ep0.dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;}/** * This function releases the Gadget device. * required by device_unregister(). * * @todo Should this do something?	Should it free the PCD? */static void dwc_otg_pcd_gadget_release(struct device *_dev){	DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _dev);}/** * This function initialized the PCD portion of the driver. * */int dwc_otg_pcd_init(struct lm_device *_lmdev){	static char pcd_name[] = "dwc_otg_pcd";	dwc_otg_pcd_t *pcd;	dwc_otg_core_if_t *core_if;	dwc_otg_dev_if_t *dev_if;	dwc_otg_device_t *otg_dev = lm_get_drvdata(_lmdev);	int retval = 0;	DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _lmdev);	/*	 * Allocate PCD structure	 */	pcd = kmalloc(sizeof(dwc_otg_pcd_t), GFP_KERNEL);	if (pcd == 0) {		return -ENOMEM;	}	memset(pcd, 0, sizeof(dwc_otg_pcd_t));	spin_lock_init(&pcd->lock);	otg_dev->pcd = pcd;	s_pcd = pcd;	pcd->gadget.name = pcd_name;	strcpy(pcd->gadget.dev.bus_id, "gadget");	pcd->otg_dev = lm_get_drvdata(_lmdev);	pcd->gadget.dev.parent = &_lmdev->dev;	pcd->gadget.dev.release = dwc_otg_pcd_gadget_release;	pcd->gadget.ops = &dwc_otg_pcd_ops;	core_if = GET_CORE_IF(pcd);	dev_if = core_if->dev_if;	if (core_if->hwcfg4.b.ded_fifo_en) {		DWC_PRINT("Dedicated Tx FIFOs mode\n");	} else {		DWC_PRINT("Shared Tx FIFO mode\n");	}	/* If the module is set to FS or if the PHY_TYPE is FS then the gadget	 * should not report as dual-speed capable.      replace the following line	 * with the block of code below it once the software is debugged for	 * this.  If is_dualspeed = 0 then the gadget driver should not report	 * a device qualifier descriptor when queried. */	if ((GET_CORE_IF(pcd)->core_params->speed == DWC_SPEED_PARAM_FULL) ||	    ((GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type == 2) &&	     (GET_CORE_IF(pcd)->hwcfg2.b.fs_phy_type == 1) &&	     (GET_CORE_IF(pcd)->core_params->ulpi_fs_ls))) {		pcd->gadget.is_dualspeed = 0;	} else {		pcd->gadget.is_dualspeed = 1;	}	if ((otg_dev->core_if->hwcfg2.b.op_mode == DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE) ||	    (otg_dev->core_if->hwcfg2.b.op_mode == DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST) ||	    (otg_dev->core_if->hwcfg2.b.op_mode == DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE) ||	    (otg_dev->core_if->hwcfg2.b.op_mode == DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) {		pcd->gadget.is_otg = 0;	} else {		pcd->gadget.is_otg = 1;	}	pcd->driver = 0;	/* Register the gadget device */	device_register(&pcd->gadget.dev);	/*	 * Initialized the Core for Device mode.	 */	if (dwc_otg_is_device_mode(core_if)) {		dwc_otg_core_dev_init(core_if);	}	/*	 * Initialize EP structures	 */	dwc_otg_pcd_reinit(pcd);	/*	 * Register the PCD Callbacks.	 */	dwc_otg_cil_register_pcd_callbacks(otg_dev->core_if, &pcd_callbacks, pcd);	/*	 * Setup interupt handler	 */	DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n", _lmdev->irq);	retval = request_irq(_lmdev->irq, dwc_otg_pcd_irq, SA_SHIRQ, pcd->gadget.name, pcd);	if (retval != 0) {		DWC_ERROR("request of irq%d failed\n", _lmdev->irq);		kfree(pcd);		return -EBUSY;	}	/*	 * Initialize the DMA buffer for SETUP packets	 */	if (GET_CORE_IF(pcd)->dma_enable) {		pcd->setup_pkt =			dma_alloc_coherent(NULL, sizeof(*pcd->setup_pkt) * 5,					   &pcd->setup_pkt_dma_handle, 0);		pcd->status_buf =			dma_alloc_coherent(NULL, sizeof(uint16_t), &pcd->status_buf_dma_handle, 0);		if (GET_CORE_IF(pcd)->dma_desc_enable) {			dev_if->setup_desc_addr[0] = ep_alloc_desc(&dev_if->dma_setup_desc_addr[0]);			dev_if->setup_desc_addr[1] = ep_alloc_desc(&dev_if->dma_setup_desc_addr[1]);			dev_if->in_desc_addr = ep_alloc_desc(&dev_if->dma_in_desc_addr);			dev_if->out_desc_addr = ep_alloc_desc(&dev_if->dma_out_desc_addr);		}	} else {		pcd->setup_pkt = kmalloc(sizeof(*pcd->setup_pkt) * 5, GFP_KERNEL);		pcd->status_buf = kmalloc(sizeof(uint16_t), GFP_KERNEL);	}	if (pcd->setup_pkt == 0) {		kfree(pcd);		return -ENOMEM;	}	/* Initialize tasklet */	start_xfer_tasklet.data = (unsigned long) pcd;	pcd->start_xfer_tasklet = &start_xfer_tasklet;	return 0;}/** * Cleanup the PCD. */void dwc_otg_pcd_remove(struct lm_device *_lmdev){	dwc_otg_device_t *otg_dev = lm_get_drvdata(_lmdev);	dwc_otg_pcd_t *pcd = otg_dev->pcd;	dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;	DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _lmdev);	/*	 * Free the IRQ	 */	free_irq(_lmdev->irq, pcd);	/* start with the driver above us */	if (pcd->driver) {		/* should have been done already by driver model core */		DWC_WARN("driver '%s' is still registered\n", pcd->driver->driver.name);		usb_gadget_unregister_driver(pcd->driver);	}	device_unregister(&pcd->gadget.dev);	if (GET_CORE_IF(pcd)->dma_enable) {		dma_free_coherent(NULL, sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt,				  pcd->setup_pkt_dma_handle);		dma_free_coherent(NULL, sizeof(uint16_t), pcd->status_buf,				  pcd->status_buf_dma_handle);		if (GET_CORE_IF(pcd)->dma_desc_enable) {			ep_free_desc(dev_if->setup_desc_addr[0], dev_if->dma_setup_desc_addr[0]);			ep_free_desc(dev_if->setup_desc_addr[1], dev_if->dma_setup_desc_addr[1]);			ep_free_desc(dev_if->in_desc_addr, dev_if->dma_in_desc_addr);			ep_free_desc(dev_if->out_desc_addr, dev_if->dma_out_desc_addr);		}	} else {		kfree(pcd->setup_pkt);		kfree(pcd->status_buf);	}	kfree(pcd);	otg_dev->pcd = 0;}/** * This function registers a gadget driver with the PCD. * * When a driver is successfully registered, it will receive control * requests including set_configuration(), which enables non-control * requests.  then usb traffic follows until a disconnect is reported. * then a host may connect again, or the driver might get unbound. * * @param _driver The driver being registered */int usb_gadget_register_driver(struct usb_gadget_driver *_driver){	int retval;	DWC_DEBUGPL(DBG_PCD, "registering gadget driver '%s'\n", _driver->driver.name);	if (!_driver || _driver->speed == USB_SPEED_UNKNOWN ||	    !_driver->bind || !_driver->unbind || !_driver->disconnect || !_driver->setup) {		DWC_DEBUGPL(DBG_PCDV, "EINVAL\n");		return -EINVAL;	}	if (s_pcd == 0) {		DWC_DEBUGPL(DBG_PCDV, "ENODEV\n");		return -ENODEV;	}	if (s_pcd->driver != 0) {		DWC_DEBUGPL(DBG_PCDV, "EBUSY (%p)\n", s_pcd->driver);		return -EBUSY;	}	/* hook up the driver */	s_pcd->driver = _driver;	s_pcd->gadget.dev.driver = &_driver->driver;	DWC_DEBUGPL(DBG_PCD, "bind to driver %s\n", _driver->driver.name);	retval = _driver->bind(&s_pcd->gadget);	if (retval) {		DWC_ERROR("bind to driver %s --> error %d\n", _driver->driver.name, retval);		s_pcd->driver = 0;		s_pcd->gadget.dev.driver = 0;		return retval;	}	DWC_DEBUGPL(DBG_ANY, "registered gadget driver '%s'\n", _driver->driver.name);	return 0;}EXPORT_SYMBOL(usb_gadget_register_driver);/** * This function unregisters a gadget driver * * @param _driver The driver being unregistered */int usb_gadget_unregister_driver(struct usb_gadget_driver *_driver){	//DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, _driver);	if (s_pcd == 0) {		DWC_DEBUGPL(DBG_ANY, "%s Return(%d): s_pcd==0\n", __func__, -ENODEV);		return -ENODEV;	}	if (_driver == 0 || _driver != s_pcd->driver) {		DWC_DEBUGPL(DBG_ANY, "%s Return(%d): driver?\n", __func__, -EINVAL);		return -EINVAL;	}	_driver->unbind(&s_pcd->gadget);	s_pcd->driver = 0;	DWC_DEBUGPL(DBG_ANY, "unregistered driver '%s'\n", _driver->driver.name);	return 0;}EXPORT_SYMBOL(usb_gadget_unregister_driver);#endif				/* DWC_HOST_ONLY */

⌨️ 快捷键说明

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