#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/string.h>
#include "virt_bus_core.h"
extern struct device_type virt_client_type;
const struct virt_device_id *virt_match_id(const struct virt_device_id *id,
const struct virt_client *client)
{
if (!(id && client))
return NULL;
while (id->name[0]) {
if (strcmp(client->name, id->name) == 0)
return id;
id++;
}
return NULL;
}
struct virt_client *virt_verify_client(struct device *dev)
{
return (dev->type == &virt_client_type)
? to_virt_client(dev)
: NULL;
}
static int virt_device_match(struct device *dev, struct device_driver *drv)
{
struct virt_client *client = virt_verify_client(dev);
struct virt_driver *driver;
driver = to_virt_driver(drv);
/* Finally an virt match */
if (virt_match_id(driver->id_table, client))
return 1;
return 0;
}
static int virt_device_probe(struct device *dev)
{
struct virt_client *client = virt_verify_client(dev);
struct virt_driver *driver;
int status;
if (!client)
return 0;
driver = to_virt_driver(dev->driver);
if (driver->probe)
status = driver->probe(client,
virt_match_id(driver->id_table, client));
else
status = -EINVAL;
return status;
}
static int virt_device_remove(struct device *dev)
{
struct virt_client *client = virt_verify_client(dev);
struct virt_driver *driver;
int status = 0;
if (!client || !dev->driver)
return 0;
driver = to_virt_driver(dev->driver);
if (driver->remove) {
dev_dbg(dev, "remove\n");
status = driver->remove(client);
}
return status;
}
static void virt_client_dev_release(struct device *dev)
{
kfree(to_virt_client(dev));
}
static ssize_t
show_name(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", dev->type == &virt_client_type ?
to_virt_client(dev)->name : "unknown");
}
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
static struct attribute *virt_dev_attrs[] = {
&dev_attr_name.attr,
NULL
};
ATTRIBUTE_GROUPS(virt_dev);
struct bus_type virt_bus_type = {
.name = "virt_bus",
.match = virt_device_match,
.probe = virt_device_probe,
.remove = virt_device_remove,
};
EXPORT_SYMBOL_GPL(virt_bus_type);
struct device_type virt_client_type = {
.name = "virt_client_device",
.groups = virt_dev_groups,
.release = virt_client_dev_release,
};
EXPORT_SYMBOL_GPL(virt_client_type);
struct virt_client *
virt_register_device(struct virt_board_info const *info)
{
struct virt_client *client;
int status;
client = kzalloc(sizeof(*client), GFP_KERNEL);
if (!client)
return ERR_PTR(-ENOMEM);
client->addr = info->addr;
strlcpy(client->name, info->type, sizeof(client->name));
client->dev.bus = &virt_bus_type;
client->dev.type = &virt_client_type;
dev_set_name(&client->dev, "%s-%04x", info->type, info->addr);
status = device_register(&client->dev);
if (status)
goto out_err_silent;
printk("device [%s] registered\n", client->name);
return client;
out_err_silent:
kfree(client);
return ERR_PTR(status);
}
EXPORT_SYMBOL_GPL(virt_register_device);
void virt_unregister_device(struct virt_client *client)
{
if (IS_ERR_OR_NULL(client))
return;
device_unregister(&client->dev);
}
EXPORT_SYMBOL_GPL(virt_unregister_device);
int virt_register_driver(struct module *owner, struct virt_driver *driver)
{
int res;
/* add the driver to the list of virt drivers in the driver core */
driver->driver.owner = owner;
driver->driver.bus = &virt_bus_type;
/* When registration returns, the driver core
* will have called probe() for all matching-but-unbound devices.
*/
res = driver_register(&driver->driver);
if (res)
return res;
printk("driver [%s] registered\n", driver->driver.name);
return 0;
}
EXPORT_SYMBOL(virt_register_driver);
void virt_unregister_driver(struct virt_driver *driver)
{
driver_unregister(&driver->driver);
printk("driver [%s] unregistered\n", driver->driver.name);
}
EXPORT_SYMBOL(virt_unregister_driver);
static int __init virt_bus_core_init(void)
{
int retval;
retval = bus_register(&virt_bus_type);
if (retval)
return retval;
return 0;
}
static void __exit virt_bus_core_exit(void)
{
bus_unregister(&virt_bus_type);
}
module_init(virt_bus_core_init);
module_exit(virt_bus_core_exit);
MODULE_LICENSE("GPL");
linux总线设备驱动模型的demo code
需积分: 0 131 浏览量
2023-04-29
12:45:40
上传
评论
收藏 15KB RAR 举报
ZHONGCAI0901
- 粉丝: 196
- 资源: 31