USB 传输的核心是 endpoint,使用 endpoint 可以收发数据。在 endpoint 之上,就可以模拟 USB 串口、USB 触碰屏、USB 摄像头。基于这个角度,Gadget 框架可以分为两层:
不同平台采用的 USB 控制器型号不同,确认型号方法是从 dtb 反编译,找到包含 otg 字符的节点,在 Linux code 中搜索 dts 节点的 compatible,可以找到对应的 usb 从机控制器驱动。
对于底层 endpoint 的代码,需要从 UDC 驱动开始分析:
Linux-4.9.88driversusbchipideaci_hdrc_imx.c
ci_hdrc_imx_probe
ci_hdrc_add_device
pdev = platform_device_alloc("ci_hdrc", id);
// Linux-4.9.88driversusbchipideacore.c
static struct platform_driver ci_hdrc_driver = {
.probe = ci_hdrc_probe,
.remove = ci_hdrc_remove,
.driver = {
.name = "ci_hdrc",
.pm = &ci_pm_ops,
},
};
ci_hdrc_probe
ret = ci_hdrc_gadget_init(ci);
udc_start
Linux-5.4driversusbdwc2platform.c
dwc2_driver_probe
retval = dwc2_gadget_init(hsotg);
模拟各类 USB 设备时,软件怎么分层?以访问设备、获取描述符为例:
所以,从获取描述符的角度看看,上层软件至少分为 2 层:
软件层次可以进一步细化,如下图:
这涉及 2 个结构体:
struct usb_composite_dev {
struct usb_gadget *gadget;
struct usb_request *req;
struct usb_request *os_desc_req;
struct usb_configuration *config;
/* OS String is a custom (yet popular) extension to the USB standard. */
u8 qw_sign[OS_STRING_QW_SIGN_LEN];
u8 b_vendor_code;
struct usb_configuration *os_desc_config;
unsigned int use_os_string:1;
/* private: */
/* internals */
unsigned int suspended:1;
struct usb_device_descriptor desc;
struct list_head configs;
struct list_head gstrings;
struct usb_composite_driver *driver;
u8 next_string_id;
char *def_manufacturer;
/* the gadget driver won't enable the data pullup
* while the deactivation count is nonzero.
*/
unsigned deactivations;
/* the composite driver won't complete the control transfer's
* data/status stages till delayed_status is zero.
*/
int delayed_status;
/* protects deactivations and delayed_status counts*/
spinlock_t lock;
/* public: */
unsigned int setup_pending:1;
unsigned int os_desc_pending:1;
};
struct usb_udc {
struct usb_gadget_driver *driver;
struct usb_gadget *gadget;
struct device dev;
struct list_head list;
bool vbus;
};
全部0条评论
快来发表一下你的评论吧 !