Linux设备驱动模型2——总线式设备驱动组织方式(总线、设备、驱动、类等结构体)

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。

参考

Linux总线设备驱动模型的理解

struct class 和 struct class_device

前言

这里说的“总线式”,包括I2C总线等具体物理总线,以及平台总线这个虚拟总线。

root@ubuntu:/sys# ls
block  bus  class  dev  devices  firmware  fs  hypervisor  kernel  module  power
root@ubuntu:/sys# cd bus/
root@ubuntu:/sys/bus# ls
ac97         eisa          isa           pci_express  sdio        virtio
acpi         event_source  machinecheck  platform     serio       workqueue
clockevents  gameport      mdio_bus      pnp          spi         xen
clocksource  hid           mmc           rapidio      usb         xen-backend
cpu          i2c           pci           scsi         usb-serial
root@ubuntu:/sys/bus# cd platform/
root@ubuntu:/sys/bus/platform# ls
devices  drivers  drivers_autoprobe  drivers_probe  uevent
root@ubuntu:/sys/bus/platform# cd ../i2c
root@ubuntu:/sys/bus/i2c# ls
devices  drivers  drivers_autoprobe  drivers_probe  uevent
root@ubuntu:/sys/bus/i2c# 

1、总线:struct bus_type结构体

(1)物理上的真实总线及其作用

(2)驱动框架中的总线式设计

总线管理设备(有一个设备链表)和驱动(有一个驱动链表),它们通过名字来匹配。

(3)结构体struct bus_type

该结构体位于x210kernel/inclue/linux/device.h文件中。

struct bus_type {
	const char		*name; //总线的名字
	struct bus_attribute	*bus_attrs;
	struct device_attribute	*dev_attrs;
	struct driver_attribute	*drv_attrs;
   
    //match函数(负责设备和驱动的匹配) 
	int (*match)(struct device *dev, struct device_driver *drv);
	int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
	int (*probe)(struct device *dev);
	int (*remove)(struct device *dev);
	void (*shutdown)(struct device *dev);

	int (*suspend)(struct device *dev, pm_message_t state);
	int (*resume)(struct device *dev);

	const struct dev_pm_ops *pm;

	struct bus_type_private *p;
};

2、设备:struct device结构体

(1)结构体struct device是硬件设备在内核驱动框架中的抽象。

该结构体位于x210kernel/inclue/linux/device.h文件中。

struct device {
	struct device		*parent;
	struct device_private	*p;
	struct kobject kobj;
	const char		*init_name; /* initial name of the device */
	struct device_type	*type;
	struct mutex		mutex;	/* mutex to synchronize calls to
					 * its driver.
					 */

	struct bus_type	*bus;		/* type of bus device is on */
	struct device_driver *driver;	/* which driver has allocated this
					   device */
	void		*platform_data;	/* Platform specific data, device
					   core doesn't touch it */
	struct dev_pm_info	power;

#ifdef CONFIG_NUMA
	int		numa_node;	/* NUMA node this device is close to */
#endif
	u64		*dma_mask;	/* dma mask (if dma'able device) */
	u64		coherent_dma_mask;/* Like dma_mask, but for
					     alloc_coherent mappings as
					     not all hardware supports
					     64 bit addresses for consistent
					     allocations such descriptors. */

	struct device_dma_parameters *dma_parms;

	struct list_head	dma_pools;	/* dma pools (if dma'ble) */

	struct dma_coherent_mem	*dma_mem; /* internal for coherent mem
					     override */
	/* arch specific additions */
	struct dev_archdata	archdata;
#ifdef CONFIG_OF
	struct device_node	*of_node;
#endif

	dev_t			devt;	/* dev_t, creates the sysfs "dev" */

	spinlock_t		devres_lock;
	struct list_head	devres_head;

	struct klist_node	knode_class;
	struct class		*class;
	const struct attribute_group **groups;	/* optional groups */

	void	(*release)(struct device *dev);
};

(2)device_register由内核开发者提供的框架提供,用于向内核驱动框架注册一个设备。

(3)struct device通常被包含在一个具体设备结构体中。

比如struct usb_device:

struct usb_device {
	int		devnum;
	char		devpath[16];
	u32		route;
	enum usb_device_state	state;
	enum usb_device_speed	speed;

	struct usb_tt	*tt;
	int		ttport;

	unsigned int toggle[2];

	struct usb_device *parent;
	struct usb_bus *bus;
	struct usb_host_endpoint ep0;

	struct device dev;

	struct usb_device_descriptor descriptor;
	struct usb_host_config *config;

	struct usb_host_config *actconfig;
	struct usb_host_endpoint *ep_in[16];
	struct usb_host_endpoint *ep_out[16];

	char **rawdescriptors;

	unsigned short bus_mA;
	u8 portnum;
	u8 level;

	unsigned can_submit:1;
	unsigned persist_enabled:1;
	unsigned have_langid:1;
	unsigned authorized:1;
	unsigned authenticated:1;
	unsigned wusb:1;
	int string_langid;

	/* static strings from the device */
	char *product;
	char *manufacturer;
	char *serial;

	struct list_head filelist;
#ifdef CONFIG_USB_DEVICE_CLASS
	struct device *usb_classdev;
#endif
#ifdef CONFIG_USB_DEVICEFS
	struct dentry *usbfs_dentry;
#endif

	int maxchild;
	struct usb_device *children[USB_MAXCHILDREN];

	u32 quirks;
	atomic_t urbnum;

	unsigned long active_duration;

#ifdef CONFIG_PM
	unsigned long last_busy;
	int autosuspend_delay;
	unsigned long connect_time;

	unsigned do_remote_wakeup:1;
	unsigned reset_resume:1;
#endif
	struct wusb_dev *wusb_dev;
	int slot_id;
};

比如 struct platform_device:

struct platform_device {
	const char	* name;
	int		id;
	struct device	dev;//!!!!
	u32		num_resources;
	struct resource	* resource;

	const struct platform_device_id	*id_entry;

	/* arch specific additions */
	struct pdev_archdata	archdata;
};

3、驱动:struct device_driver结构体

(1)结构体struct device_driver是驱动程序在内核驱动框架中的抽象。

该结构体位于x210kernel/inclue/linux/device.h文件中。

struct device_driver {
	const char		*name; //驱动程序的名字,被用来作为驱动和设备的匹配依据
	struct bus_type		*bus;

	struct module		*owner;
	const char		*mod_name;	/* used for built-in modules */

	bool suppress_bind_attrs;	/* disables bind/unbind via sysfs */

#if defined(CONFIG_OF)
	const struct of_device_id	*of_match_table;
#endif
    
    //驱动程序的探测函数,用来检测某个设备是否可以被该驱动所管理
    //比如该设备是否正常、以及一些初始化。见参考微博的描述。
	int (*probe) (struct device *dev);

	int (*remove) (struct device *dev);
	void (*shutdown) (struct device *dev);
	int (*suspend) (struct device *dev, pm_message_t state);
	int (*resume) (struct device *dev);
	const struct attribute_group **groups;

	const struct dev_pm_ops *pm;

	struct driver_private *p;
};

(2)struct platform_driver的内容如下

struct platform_driver {
	int (*probe)(struct platform_device *);
	int (*remove)(struct platform_device *);
	void (*shutdown)(struct platform_device *);
	int (*suspend)(struct platform_device *, pm_message_t state);
	int (*resume)(struct platform_device *);
	struct device_driver driver;
	const struct platform_device_id *id_table;
};

4、类:struct class结构体

(1)相关结构体:struct class(类) 和 struct class_device(类下面的某个设备)

结构体struct class在x210kernel/inclue/linux/device.h文件中定义:

struct class {
	const char		*name;
	struct module		*owner;

	struct class_attribute		*class_attrs;
	struct device_attribute		*dev_attrs;
	struct kobject			*dev_kobj;

	int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
	char *(*devnode)(struct device *dev, mode_t *mode);

	void (*class_release)(struct class *class);
	void (*dev_release)(struct device *dev);

	int (*suspend)(struct device *dev, pm_message_t state);
	int (*resume)(struct device *dev);

	const struct kobj_ns_type_operations *ns_type;
	const void *(*namespace)(struct device *dev);

	const struct dev_pm_ops *pm;

	struct class_private *p;
};

结构体struct class_device:该结构体好像已经不再使用了?怎么查询不到的!

(2)udev的使用离不开class。class的意义在于作为同属于一个class的多个设备的容器。也就是说class是一种人造概念,目的就是为了对各种设备进行分类管理。当然,class在分类的同时还对每个类贴上了一些“标签”,这也是设备驱动模型为我们写驱动提供的基础设施。

5、总结:模型即面向对象的思想

(1)模型,其实就是面向对象的思想。

(2)这些模型里全是一些结构体套结构体,因此对基本功要求很高。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天糊土

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值