#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/pm.h>
#include <asm/uaccess.h>

static int major=0;
static int suspend_count = 0;

int my_suspend(struct device *dev, pm_message_t state)
{
   suspend_count++;
   switch (state.event) {
   case PM_EVENT_ON:
       printk("on ...\n"); break;
   case PM_EVENT_FREEZE:
       printk("freeze ...\n"); break;
   case PM_EVENT_SUSPEND:
       printk("suspend ...\n"); break;
   case PM_EVENT_HIBERNATE:
       printk("hibernate ...\n"); break;
   default:
       printk("pm_event: 0x%x\n", state.event); break;
   }
   printk("my_suspend(%p, %d)\n", dev, suspend_count);
   return 0;
}

int my_resume(struct device *dev)
{
   suspend_count++;
   printk("my_resume(%p, %d)\n", dev, suspend_count );
   return 0;
}

static struct file_operations fops = {
   .owner = THIS_MODULE,
};

static struct class *test_class;

static int __init my_module_init(void)
{
   printk("my_module_init\n");
   if ((major = register_chrdev(0, "testdev", &fops))) {
       test_class = class_create(THIS_MODULE, "testclass");
       if (IS_ERR(test_class)) {
           printk("no udev support\n");
           unregister_chrdev(major, "testdev");
           return -EIO;
       }
       test_class->suspend = my_suspend;
       test_class->resume = my_resume;
       device_create(test_class, NULL, MKDEV(major, 0), "lulu");
       return 0;
   }
   printk("loading failed\n");
   return -EIO;
}

static void __exit my_module_exit(void)
{
   unregister_chrdev(major, "testdev");
   if (!IS_ERR(test_class)) {
       device_destroy(test_class, MKDEV(major, 0));
       class_destroy(test_class);
   }
   printk("my_module_exit; %d times suspended\n", suspend_count);
}

module_init(my_module_init);
module_exit(my_module_exit);
MODULE_LICENSE("GPL");