【学習ノート】番犬サブシステム

7206 ワード

サブシステムは、ユーザが再作成する必要がなく、対応する構造体にデバイス情報を記入する必要がある一連の操作を提供する.
 struct watchdog_device {
         int id;
         struct cdev cdev;
         struct device *dev;
         struct device *parent;
         const struct watchdog_info *info;
         const struct watchdog_ops *ops;
         unsigned int bootstatus;
         unsigned int timeout;
         unsigned int min_timeout;
         unsigned int max_timeout;
         void *driver_data;
         struct mutex lock;
         unsigned long status;
 /* Bit numbers for status flags */
 #define WDOG_ACTIVE             0       /* Is the watchdog running/active */
 #define WDOG_DEV_OPEN           1       /* Opened via /dev/watchdog ? */
 #define WDOG_ALLOW_RELEASE      2       /* Did we receive the magic char ? */
 #define WDOG_NO_WAY_OUT         3       /* Is 'nowayout' feature set ? */
 #define WDOG_UNREGISTERED       4       /* Has the device been unregistered */ };

主な関数:登録、ログアウト.
extern int watchdog_register_device(struct watchdog_device *); extern void watchdog_unregister_device(struct watchdog_device *);
カスタム構造体の初期化:
#define OPTIONS (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE)


    static const struct watchdog_info s3c2410_wdt_ident = {
                    .options          =     OPTIONS,
                    .firmware_version = 0,
                    .identity         = "S3C2410 Watchdog",
            };


    static struct watchdog_ops s3c2410wdt_ops = {
                    .owner = THIS_MODULE,
                    .start = s3c2410wdt_start,                  static struct watchdog_device s3c2410_wdd = {
                    .info = &s3c2410_wdt_ident,
                    .ops = &s3c2410wdt_ops,
            };
//watchdog/watchdog_core.c:
    int watchdog_register_device(struct watchdog_device *wdd)
        ret = watchdog_dev_register(wdd);
        devno = wdd->cdev.dev;
        wdd->dev = device_create(watchdog_class, wdd->parent, devno, NULL, "watchdog%d", wdd->id);

        watchdog/watchdog_dev.c
                static const struct file_operations watchdog_fops = {
                        .owner      = THIS_MODULE,
                        .write      = watchdog_write,
                        .unlocked_ioctl = watchdog_ioctl,
                        .open       = watchdog_open,
                        .release    = watchdog_release,
                };

        static struct miscdevice watchdog_miscdev = {
                        .minor      = WATCHDOG_MINOR,
                        .name       = "watchdog",
                        .fops       = &watchdog_fops,
                };

                int watchdog_dev_register(struct watchdog_device *watchdog) {
                    if (watchdog->id == 0) {
                        watchdog_miscdev.parent = watchdog->parent;
                        err = misc_register(&watchdog_miscdev);
                        ...
                        old_wdd = watchdog;
                    }

                    devno = MKDEV(MAJOR(watchdog_devt), watchdog->id);
                    cdev_init(&watchdog->cdev, &watchdog_fops);
                    watchdog->cdev.owner = watchdog->ops->owner;

                    /* Add the device */
                    err  = cdev_add(&watchdog->cdev, devno, 1);

                }

        static long watchdog_ioctl(struct file *file, unsigned int cmd,
                                    unsigned long arg)
        {
                WDIOC_GETSUPPORT:
                    return copy_to_user(argp, wdd->info,
                            sizeof(struct watchdog_info)) ? -EFAULT : 0;
                WDIOC_GETSTATUS:

                WDIOC_GETBOOTSTATUS:

                WDIOC_SETOPTIONS:
                    if (val & WDIOS_DISABLECARD) {
                            err = watchdog_stop(wdd);
                            if (err < 0)
                                    return err;
                    }
                    if (val & WDIOS_ENABLECARD) {
                            err = watchdog_start(wdd);
                            if (err < 0)
                                    return err;
                    }

                WDIOC_KEEPALIVE:
                    if (!(wdd->info->options & WDIOF_KEEPALIVEPING))
                        return -EOPNOTSUPP;
                    watchdog_ping(wdd);

                WDIOC_SETTIMEOUT:
                    err = watchdog_set_timeout(wdd, val);
                    watchdog_ping(wdd);

                WDIOC_GETTIMEOUT:

                WDIOC_GETTIMELEFT: