自娱自乐1之Linux UDC驱动(形式模板)

本文作者分享了个人在学习Linux UDC驱动时的自娱自乐项目,探讨了UDC和gadget驱动的相关资料稀缺情况,并提供了一个未实际应用的模板。该模板涉及常用结构体、请求队列处理、endpoint初始化等方面,但尚未实现DMA和USB请求类型的处理。作者计划以此为基础,逐步完善并应用于实际驱动开发。
摘要由CSDN通过智能技术生成


首先,我不是做驱动的开发人员。所以只能用自娱自乐来表示我的行为。

我不知道udc和gadget驱动是不是冷门的驱动,资料真是不多。我之前买了一本书,上面说到这些,就教你如何调试已写好的驱动。这样也可以写书,太坑了吧!我随便从网上搜搜都能写的比他好。难道现在的育人机构为了钱都变成了坑人机构。

我以前就希望把自己写过的驱动总结成一个模板,让人能直观的看出linux提供的接口要我们做什么甚至怎么做。虽然做这个比较难,但我还是成功的欺骗了自己,可以做到。

这是自娱自乐第一期,可能废话多了一点,请大家原谅。现在说这个模板。这个是一个未做实际应用的模板,只是编译通过,除了没实践,还缺少DMA和USB的请求类型处理样例。后期我会用它做一个驱动,不断的完善。现在这个应该在理论和实践之间的东西。

常用结构体(别人写的,不是linux-3.2.36,不过差不多)

========================================================USB UDC与gadget驱动=========================================================
/*
 *linux内核中usb设备侧驱动程序分为3个层次:UDC驱动、Gadget API和Gadget驱动程序,UDC驱动程序直接访问硬件usb控制器OHCI/EHCI/UHCI,作为usb设备和主机间的底层通信,向上层
 *提供与硬件相关操作的回调函数。当前Gadget API是对UDC驱动程序回调函数的简单包装。Gadget驱动程序具体控制系统作为usb设备时的相关功能的实现,使设备表现出“网络连接”、“打印机”
 *或“USB Mass Storage”等特性。
 *
 *    这里的USB设备控制器(UDC)驱动指作为其他USB主机控制器外设的USB硬件设备上底层硬件控制器的驱动,该硬件和驱动负责将USB设备依附于一个USB主机控制器上:比如当某运行linux的手机作为PC
 *的U盘时,手机的底层USB控制器行使USB设备控制器的功能,这时候运行在底层的是UDC驱动,而手机成为U盘,在UDC驱动之上仍然需要另一个驱动,对于USB大容量存储器为file storage驱动,这一
 *驱动称为gadget驱动(总之是一个运行linux的系统的usb接口作为另一个linux系统的设备)。usb设备驱动调用usb核心提供的API,因此具体驱动与SOC无关。同样,usb gadget驱动调用通用的gadget API
 *因此具体gadget驱动也变得与SOC无关。
 *UDC驱动和gadget驱动都位于内核的drivers/usb/gadget目录下,S3C2410对应的UDC驱动为s3c2410_udc.c。ether.c、f_serial.c、file_storage.c等文件实现了一些gadget驱动
 */
#include <linux/gadget.h>

-----------------------------------------------------------struct usb_gadget------------------------------------------------------
struct usb_gadget {   //描述USB设备控制器
	/* readonly to gadget driver */                  //针对gadget驱动只读
	const struct usb_gadget_ops	*ops;                //访问硬件函数
	struct usb_ep			*ep0;                          //端点0,setup使用
	struct list_head		ep_list;	/* of usb_ep */    //其他端点列表
	enum usb_device_speed		speed;                   
	unsigned			is_dualspeed:1;
	unsigned			is_otg:1;
	unsigned			is_a_peripheral:1;
	unsigned			b_hnp_enable:1;                    //A-HOST使能了HNP支持
	unsigned			a_hnp_support:1;                   //A-HOST支持HNP
	unsigned			a_alt_hnp_support:1;
	const char			*name;
	struct device			dev;
};

------------------------------------------------------struct usb_gadget_ops-------------------------------------------------------
struct usb_gadget_ops {  //硬件操作函数
	int	(*get_frame)(struct usb_gadget *);
	int	(*wakeup)(struct usb_gadget *);
	int	(*set_selfpowered) (struct usb_gadget *, int is_selfpowered);
	int	(*vbus_session) (struct usb_gadget *, int is_active);
	int	(*vbus_draw) (struct usb_gadget *, unsigned mA);
	int	(*pullup) (struct usb_gadget *, int is_on);
	int	(*ioctl)(struct usb_gadget *,
				unsigned code, unsigned long param);
};

-----------------------------------------------------struct usb_gadget_driver----------------------------------------------------
struct usb_gadget_driver {  //描述gadget驱动
	char			*function;                          //描述gadget功能的字符串
	enum usb_device_speed	speed;
	int			(*bind)(struct usb_gadget *);         //当驱动和gadget绑定时调用
	void			(*unbind)(struct usb_gadget *);
	int			(*setup)(struct usb_gadget *,         //处理硬件驱动未处理的端点0请求
					const struct usb_ctrlrequest *);
	void			(*disconnect)(struct usb_gadget *);
	void			(*suspend)(struct usb_gadget *);
	void			(*resume)(struct usb_gadget *);

	/* FIXME support safe rmmod */
	struct device_driver	driver;
};

-----------------------------------------------------struct usb_request----------------------------------------------------------
struct usb_request {  //表示一个传输请求的usb_request(与从机端看到的urb相似)
	void			*buf;
	unsigned		length;
	dma_addr_t		dma;

	unsigned		no_interrupt:1;
	unsigned		zero:1;
	unsigned		short_not_ok:1;

	void			(*complete)(struct usb_ep *ep,
					struct usb_request *req);
	void			*context;
	struct list_head	list;

	int			status;
	unsigned		actual;
};

----------------------------------------------------------struct usb_ep---------------------------------------------------------
struct usb_ep {   //描述一个端点
	void			*driver_data;

	const char		*name;
	const struct usb_ep_ops	*ops;
	struct list_head	ep_list;
	unsigned		maxpacket:16;
};

------------------------------------------------------struct usb_ep_ops---------------------------------------------------------
struct usb_ep_ops {   //描述端点操作
	int (*enable) (struct usb_ep *ep,
		const struct usb_endpoint_descriptor *desc);
	int (*disable) (struct usb_ep *ep);

	struct usb_request *(*alloc_request) (struct usb_ep *ep,
		gfp_t gfp_flags);
	void (*free_request) (struct usb_ep *ep, struct usb_request *req);

	int (*queue) (struct usb_ep *ep, struct usb_request *req,
		gfp_t gfp_flags);
	int (*dequeue) (struct usb_ep *ep, struct usb_request *req);

	int (*set_halt) (struct usb_ep *ep, int value);
	int (*set_wedge) (struct usb_ep *ep);

	int (*fifo_status) (struct usb_ep *ep);
	void (*fifo_flush) (struct usb_ep *ep);
};
--------------------------------------------------------------------------------------------------------------------------------
/*
 *UDC和gadget驱动围绕上述数据结构及其成员函数而展开。 
 *在具体的UDC驱动中,需要封装usb_gadget和每个端点usb_ep,实现端点usb_ep_ops,完成usb_request。另外usb_gadget_register_driver和usb_gadget_unregister_driver这两个API需要由UDC
 *驱动提供,gadget驱动会调用它们。
 */
int usb_gadget_register_driver(struct usb_gadget_driver *driver); //注册,在加载模块中调用,该函数中会调用driver->bind()函数,将usb_gadget_driver与具体的gadget绑定
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver); //注销,在卸载模块中调用,告诉UDC驱动不再投入工作,如果UDC正在和USB主机连接,会先调用driver->disconnect()
                                                                    //函数,而后会调用unbind()函数
//在linux/usb/gadget.h中,封装了一些常用的API:                                                                    
int usb_ep_enable(struct usb_ep *ep,const struct usb_endpoint_descriptor *desc);  //使能端点 ,该函数会调用struct usb_ep_ops->enable()
int usb_ep_disable(struct usb_ep *ep);  //禁止端点,该函数会调用struct usb_ep_ops->disable()

struct usb_request *usb_ep_alloc_request(struct usb_ep *ep,gfp_t gfp_flags);    //分配一个依附于某端点的 usb_request,该函数会调用struct usb_ep_ops->usb_request()
void usb_ep_free_request(struct usb_ep *ep,struct usb_request *req);            //释放一个依附于某端点的 usb_request,该函数会调用struct usb_ep_ops->free_request()

int usb_ep_queue(struct usb_ep *ep, struct usb_request *req, gfp_t gfp_flags);//提交usb_request,该函数告诉UDC完成usb_request(读写buffer),当请求被完成后,该请求对应的completion函数会被调用,
                                                                              //该函数会调用struct usb_ep_ops->queue(),该函数告诉UDC完成usb_request(读写buffer),当请求完成后,该请求对应的completion函数会被调用
int usb_ep_dequeue(struct usb_ep *ep, struct usb_request *req);  //取消usb_request,该函数会调用struct usb_ep_ops->dequeue()

端点FIFO管理:
int usb_ep_fifo_status(struct usb_ep *ep);  //该函数会调用truct usb_ep_ops->fifo_status返回目前FIFO中的字节数
void usb_ep_fifo_flush(struct usb_ep *ep);  //该函数会调用truct usb_ep_ops->fifo_flush,以flush(冲洗)掉FIFO中的数据

int usb_gadget_frame_number(struct usb_gadget *gadget); //它调用gadget->ops->get_frame(gadget)返回目前的帧号

/*
 *S3C2410的UDC驱动在 /driver/usb/gadget/s3c2410_udc.c
 */
/-----------------------------------------------------------------------------------------------------------------------------/

看请求队列的处理

struct xxxxx_request

{

    structlist_head        queue;       /* ep'srequests */

    structusb_request        req;       //对应主机端看到的urb

};

struct

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值