DM框架3-Devices

Any device in the system has a struct device structure associated with it. Devices are discovered by different kernel methods (hotplug, device drivers, system initialization) and are registered in the system. Each device present in the kernel has an entry in /sys/devices.

At the lowest level, a device in Linux Device Model is represented by a struct device structure:

struct device {
        //...
        struct device           *parent;
        struct device_private   *p;
        struct kobject          kobj;

        const char              *init_name; /* initial name of the device */
        //...
        struct bus_type         *bus;       /* type of bus device is on */
        struct device_driver    *driver;    /* which driver has allocated this
                                             device */
        //...
        void    (*release)(struct device *dev);
};

Structure fields include the parent device that is usually a controller, the associated kobject, the bus it is connected to, the device driver, and a function called when the device counter reaches 0 (release).

As usual, we have the registration/unregistration functions device_register() and device_unregister().

To work with attributes, we have structure struct device_attribute, the macro DEVICE_ATTR for definition, and the functions device_create_file() and device_remove_file() for adding/removing the attribute to/from the device.

One important thing to note is that the struct device structure is usually not used directly, but it is added to another structure. For example:

// my device type
struct my_device {
    char *name;
    struct my_driver *driver;
    struct device dev;
};

Typically, a bus driver will export functions to add or remove such a device, as shown below:

/* mybus.c */

/* BUS DEVICE (parent) */

// parent device release
static void my_bus_device_release(struct device *dev)
{
}

// parent device
static struct device my_bus_device = {
  .init_name   = "mybus0",
  .release     = my_bus_device_release
};

/* DEVICE */

/*
 * as we are not using the reference count, we use a no-op
 * release function
 */
static void my_dev_release(struct device *dev)
{
}

int my_register_device(struct my_device *mydev)
{
  mydev->dev.bus = &my_bus_type;
  mydev->dev.parent = &my_bus_device;
  mydev->dev.release = my_dev_release;
  dev_set_name(&mydev->dev, mydev->name);

  return device_register(&mydev->dev);
}

void my_unregister_device(struct my_device *mydev)
{
  device_unregister(&mydev->dev);
}

/* export register/unregister device functions */
EXPORT_SYMBOL(my_register_device);
EXPORT_SYMBOL(my_unregister_device);

As seen, the functions my_register_device and my_unregister_device, used to add/remove a device to/from a bus, are defined in the same file where the bus is defined. Device structures are not initialized; they will be initialized when the devices are discovered by the system (by hotplug or direct registration from driver) and the function my_register_device will be called to add a device to the bus.

To use the bus defined above in the driver implementation, we must define a structure of type my_device, initialize it and register it using the function exported by the bus (my_register_device).

/* mydriver.c */

static struct my_device mydev;
char devname[NAME_SIZE];
//...

//register
int err;

sprintf(devname, "mydev0");
mydev.name = devname;
mydev.driver = &mydriver;
dev_set_drvdata(&mydev.dev, &mydev);
err = my_register_device(&mydev);
if (err < 0) {
  /*handle error */
}

//..

//unregister
my_unregister_device(&mydev);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值