• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

usb udc 驱动

武飞扬头像
Water Water Water
帮助1

1. dwc3 and dummy gadget

debug:

ls /sys/class/udc 		//查看系统注册了的udc驱动

1.1 gadegt 初始化

1.1.1 dwc3 gadget 初始化

== dwc3_gadget_init(struct dwc3 *dwc);
	== dwc3_gadget_init_endpoints(dwc, dwc->num_eps);	// num_eps 从设备硬件中读取
		== dwc3_gadget_init_endpoint(dwc, epnum);		// 初始化端点
			== 	struct dwc3_ep			*dep;			// 对usb_ep 封装成dwc3_ep
				dep->number = epnum;					// dep 数量最多32 个
				dep->regs = dwc->regs   DWC3_DEP_BASE(epnum);	// 对应寄存器地址
				dwc->eps[epnum] = dep;
			== dwc3_gadget_init_in_endpoint(struct dwc3_ep *dep);
				== dep->endpoint.ops = &dwc3_gadget_ep_ops;		//usb_ep 的ops
	== usb_add_gadget(dwc->gadget);		//gadget设备:struct usb_gadget *gadget; 
		== device_add(&gadget->dev);	// 注册gadget 设备
		== list_add_tail(&udc->list, &udc_list);	//将该udc 添加到udc_list 链表,与后期gadget 匹配
		== device_add(&udc->dev);		// 注册udc 设备

1.1.2 dummy gadget 初始化

== dummy_udc_probe(struct platform_device *pdev);
	== dum->gadget.ops = &dummy_ops;
	== init_dummy_udc_hw(dum);
		== struct dummy_ep	*ep = &dum->ep[i];		// 对usb_ep 封装成dummy_ep
			ep->ep.ops = &dummy_ep_ops;				// usb_ep 的ops
			dum->gadget.ep0 = &dum->ep[0].ep;		// 端点0 比较特殊
	== usb_add_gadget_udc(&pdev->dev, &dum->gadget);
		== usb_add_gadget_udc_release(parent, gadget, NULL);
			== usb_initialize_gadget(parent, gadget, release);
			== usb_add_gadget(gadget);

1.1.3 端点 ep

usb_gadget 结构体为共有信息,含有端点0(ep0),所有设备都必须含有端点0,用于控制传输

struct usb_gadget {
	struct usb_udc			*udc;
	/* readonly to gadget driver */
	const struct usb_gadget_ops	*ops;
	struct usb_ep			*ep0;
	struct list_head		ep_list;	/* of usb_ep */
	enum usb_device_speed		speed;
	enum usb_device_speed		max_speed;

	enum usb_device_state		state;
	const char			*name;
	struct device			dev;
}

dwc3 属于私有设备信息,包含usb_gadget 信息,并含有其他端点的信息dw3_ep(封装的usb_ep)。

struct dwc3 {
	struct device		*dev;
	struct device		*sysdev;

	struct platform_device	*xhci;
	struct resource		xhci_resources[DWC3_XHCI_RESOURCES_NUM];

	struct dwc3_ep		*eps[DWC3_ENDPOINTS_NUM];

	struct usb_gadget	*gadget;
}

同样的,dummy 属于私有设备信息,包含usb_gadget 信息,并含有其他端点的信息dummy_ep(封装的usb_ep)。

struct dummy {
	// DEVICE/GADGET side support
	struct dummy_ep			ep[DUMMY_ENDPOINTS];
	int				address;
	int				callback_usage;
	struct usb_gadget		gadget;
	struct usb_gadget_driver	*driver;
	struct dummy_request		fifo_req;
	u8				fifo_buf[FIFO_SIZE];
	u16				devstatus;

	// HOST side support
	struct dummy_hcd		*hs_hcd;
	struct dummy_hcd		*ss_hcd;
}

1.2 gadget 发送数据(dwc3)

1.2.1 function 向gadget 申请req

\drivers\usb\gadget\function\f_fs.c
(1) 申请req

ffs->ep0req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);		//端点0 的传输
ffs->ep0req->complete = ffs_ep0_complete;	// req的完成函数

or

ep = usb_ep_autoconfig(func->gadget, ds);		// 从gadget 获取与description 对应的端点
req = usb_ep_alloc_request(ep, GFP_KERNEL);

(2) 将req 提交到dwc3 gadget core

== usb_ep_queue(ffs->gadget->ep0, req, GFP_ATOMIC);		//提交到ep0
== ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC);			//提交到非0 端点
	== ret = ep->ops->queue(ep, req, gfp_flags);
		== dwc3_gadget_ep_queue();

1.2.2 dwc3 gadget core 处理req (写寄存器)

== dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, gfp_t gfp_flags)
	== __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
		== __dwc3_gadget_start_isoc(struct dwc3_ep *dep)
		== __dwc3_gadget_kick_transfer(struct dwc3_ep *dep)
			== dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd, struct dwc3_gadget_ep_cmd_params *params) 	
				// This function will issue @cmd with given @params to @dep and wait for its completion.
				== dwc3_writel(void __iomem *base, u32 offset, u32 value)

1.2.3 core 返回req (中断回调函数)

== udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver)
	== usb_gadget_udc_start(struct usb_udc *udc);
		udc->gadget->ops->udc_start(udc->gadget, udc->driver);
		== dwc3_gadget_start(struct usb_gadget *g, struct usb_gadget_driver *driver)  //注册中断
			== request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt, 
								IRQF_SHARED, "dwc3", dwc->ev_buf);
	
== dwc3_thread_interrupt(int irq, void *_evt)		//中断产生,调用回调函数
	== dwc3_process_event_buf(struct dwc3_event_buffer *evt)		//处理中断事件buf
		== dwc3_process_event_entry(struct dwc3 *dwc, const union dwc3_event *event)
			== dwc3_endpoint_interrupt(struct dwc3 *dwc, const struct dwc3_event_depevt *event)
				== dwc3_gadget_endpoint_transfer_complete()		//调用req完成函数
					== dwc3_gadget_endpoint_trbs_complete()
						== dwc3_gadget_ep_cleanup_completed_requests()
							== dwc3_gadget_giveback(dep, req, status);				//数据返回
								== usb_gadget_giveback_request()	// give the request back to the gadget layer
									== req->complete(ep, req);
										== ffs_ep0_complete(struct usb_ep *ep, struct usb_request *req)	// function的完成函数
学新通

1.3 gadget 发送数据(dummy)

1.2.1 function 向gadget 申请req

dwc3 一样。

1.2.2 dummy gadget core 处理req (memcpy)

== dummy_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t mem_flags);
	/* implement an emulated single-request FIFO */
	== memcpy(dum->fifo_buf, _req->buf, _req->length);	
	== req->req.context = dum;
	== req->req.complete = fifo_complete;			//完成函数
	== list_add_tail(&req->queue, &ep->queue);
	== usb_gadget_giveback_request(_ep, _req);		//返回req,调用完成函数
		== req->complete(ep, req);

1.4 usb_gadget_ops

usb_gadget_ops函数集,这些函数主要是操作UDC设备的一些特性(针对设备)。
enable/disable gadget 的时候,会调用到相关接口。

1.4.1 dwc3

== dwc3_gadget_init(struct dwc3 *dwc)
	== dwc->gadget->ops		= &dwc3_gadget_ops;		//初始化

static const struct usb_gadget_ops dwc3_gadget_ops = {
	.get_frame		= dwc3_gadget_get_frame,
	.wakeup			= dwc3_gadget_wakeup,
	.set_selfpowered	= dwc3_gadget_set_selfpowered,
	.pullup			= dwc3_gadget_pullup,
	.udc_start		= dwc3_gadget_start,
	.udc_stop		= dwc3_gadget_stop,
	.udc_set_speed		= dwc3_gadget_set_speed,
	.udc_set_ssp_rate	= dwc3_gadget_set_ssp_rate,
	.get_config_params	= dwc3_gadget_config_params,
	.vbus_draw		= dwc3_gadget_vbus_draw,
	.check_config		= dwc3_gadget_check_config,
	.udc_async_callbacks	= dwc3_gadget_async_callbacks,
};
学新通

1.4.2 dummy

static const struct usb_gadget_ops dummy_ops = {
	.get_frame	= dummy_g_get_frame,
	.wakeup		= dummy_wakeup,
	.set_selfpowered = dummy_set_selfpowered,
	.pullup		= dummy_pullup,
	.udc_start	= dummy_udc_start,
	.udc_stop	= dummy_udc_stop,
	.udc_set_speed	= dummy_udc_set_speed,
};

1.5 usb_ep_ops

1.5.1 dwc3

== dwc3_gadget_init(struct dwc3 *dwc)
	== dwc3_gadget_init_endpoint(struct dwc3 *dwc, u8 epnum)
		== dwc3_gadget_init_in_endpoint(struct dwc3_ep *dep)
			== dep->endpoint.ops = &dwc3_gadget_ep_ops;

static const struct usb_ep_ops dwc3_gadget_ep_ops = {
	.enable		= dwc3_gadget_ep_enable,
	.disable	= dwc3_gadget_ep_disable,
	.alloc_request	= dwc3_gadget_ep_alloc_request,
	.free_request	= dwc3_gadget_ep_free_request,
	.queue		= dwc3_gadget_ep_queue,
	.dequeue	= dwc3_gadget_ep_dequeue,
	.set_halt	= dwc3_gadget_ep_set_halt,
	.set_wedge	= dwc3_gadget_ep_set_wedge,
};

1.5.2 dummy

static const struct usb_ep_ops dummy_ep_ops = {
	.enable		= dummy_enable,
	.disable	= dummy_disable,

	.alloc_request	= dummy_alloc_request,
	.free_request	= dummy_free_request,

	.queue		= dummy_queue,
	.dequeue	= dummy_dequeue,

	.set_halt	= dummy_set_halt,
	.set_wedge	= dummy_set_wedge,
};

2. dummy hcd

== dummy_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
	== usb_hcd_link_urb_to_ep(hcd, urb);
	== timer_pending(&dum_hcd->timer)
		timer_setup(&dum_hcd->timer, dummy_timer, 0);
		== dummy_timer(struct timer_list *t)
			== handle_control_request(dum_hcd, urb, &setup, &status);		//handle control requests
			== transfer(dum_hcd, urb, ep, limit, &status);		//non-control requests 
				== dummy_perform_transfer(urb, req, len);
			 		== memcpy(ubuf, rbuf, len);					//拷贝数据
			 	== usb_gadget_giveback_request(&ep->ep, &req->req);
			 		== req->complete(ep, req);
			== usb_hcd_unlink_urb_from_ep(dummy_hcd_to_hcd(dum_hcd), urb);		//return urb
			== usb_hcd_giveback_urb(dummy_hcd_to_hcd(dum_hcd), urb, status);

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgakbjc
系列文章
更多 icon
同类精品
更多 icon
继续加载