一、需
一、需求
rv1108的 usb otg做usb从设备的时候只有1,3,5,7端点可以作为输入端点。因基于rv1108的 项目特殊需求,需要将对USB device的端点2的IN操作映射到端点3的IN操作。
二、评估结果
经过分析linux kernel 的 usb gadat 驱动框架,dwc_otg_driver, usb gadget driver,uvc_gadte_drvier(composite driver),alstralive应用的 transmission模块源码,评估出无法满足将对USB device的端点2的IN操作映射到端点3的IN操作的需求。
三、分析过程
要满足需求需要满足以下三点:
1> 枚举时,给uvc_gadet driver 分配输入端点时,分配2端点,但是在dwc_otg_driver 使得给uvc_gadget_driver分配的2 IN 对应于3 IN。
2> 应用层通过系统调用往相应2端点写数据流时实际在驱动中要对3端点写数据流。
3> usb host 发起数据传输的时候,将对端点2的IN操作映射到对端点3的IN操作。
1,针对上述第一点,在uvc_gadget_driver通过usb_ep_autoconfig获取端点号时,将 structgadget 中的ep list的ep2in对应于 dwc_otg_driver的输入端点表中的端点地址为3的端点即可。修改top_dir/drivers/usb/dwc_otg_driver_310/dwc_otg_pcd_linux.c中的gadget_add_eps函数如下图所示:
2,针对上述第二点, alstralive应用的 transmission模块往usb device端点写数据的流程如图1(以UVC video为例):
图1
图1中,video->encode完成往usb_request.buff中填充数据的过程。它的赋值实现流程如图2;通过video->encode往usb_request.buff中填充数据之后,通过usb_ep_queue往相应端点上提交此usb_request,在usb host 发起传输指令之后会将相应端点的usb_request.buff中内容发送出去。video->encode的赋值实现流程如图3。
图2
图2中,uvc_video_alloc_request完成usb_request的申请,然后对video->encode赋值,使得其实例化。
图3
图3中对ep->ops->queue进行赋值,使得其实例化。它的具体实现在top_dir/drivers/usb/dwc_otg_driver_310/dwc_otg_pcd_linux.c的dwc_otg_pcd_ep_ops.queue;主要是将usb_request.buff进行DMA映射然后将映射出的物理地址赋值给dwc_otg device相应端点的寄存器。在将此物理地址赋值给dwc_otg device相应端点寄存器之前通过get_ep_from_handle找到dwc_otg_driver中相应的端点进行操作。get_ep_from_handle实现如图4
图4
图4中handle为uvc_gadgetdriver传递过来的usb_ep。由此函数可知,只需将uvc_gadget driver传递过来的2端点映射到pcd->in_ep[1].priv即可。 Pec->in_ep[2]为dwc_otg_driver的 第2个输入端点,端点地址为3。
这种映射方式是在usb 枚举过程中,usb host发起设置接口的请求中来完成的。具体函数是dwc_otg_pcd_ep_ops.enable=dwc_otg_pcd_ep_enable,具体修改如图5所示。
图5
通过以上修改可以满足第二点。
3,针对第三点,因为usbhost发起数据传输时,先发送的是令牌包,在令牌包中包含了端点地址,因为在usb枚举过程中已经告知usb host往2 IN操作,这些信息在令牌包中,而且由usb otg控制器来解析此包,然后向DMA发起请求向相应端点的DMA地址中去取数据,通过数据包发送给usb host。从驱动的角度无法在控制器之前知道usb host操作的是2端口,所以第三点无法满足。