#include #include #include #include #include static struct tty_driver *tty_sample_driver; static struct tty_struct *tty_sample; static ktime_t fireup_time; static struct hrtimer emu_kbd_desc; static atomic_t access_count = ATOMIC_INIT(-1); static enum hrtimer_restart emu_keyboard( struct hrtimer *hrt ) { hrtimer_forward_now( &emu_kbd_desc, ktime_set(1,0) ); tty_insert_flip_string( tty_sample, "Hi\n", 3 ); tty_flip_buffer_push( tty_sample ); return HRTIMER_RESTART; } static int tty_sample_open(struct tty_struct *tty, struct file *filp) { if (!atomic_inc_and_test(&access_count)) return -EIO; printk("tty_sample_open\n"); tty_sample = tty; fireup_time = ktime_set( 2, 0 ); hrtimer_start(&emu_kbd_desc, fireup_time, HRTIMER_MODE_REL); return 0; } static void tty_sample_close(struct tty_struct *tty, struct file *filp) { printk("tty_sample_close\n"); atomic_dec( &access_count ); if (atomic_read(&access_count)==(-1) ) hrtimer_cancel( &emu_kbd_desc ); } static int tty_sample_write(struct tty_struct *tty, const unsigned char *buf, int count) { int i; for(i=0; iowner = THIS_MODULE; tty_sample_driver->driver_name = "tty-sample"; tty_sample_driver->name = "ttySample"; tty_sample_driver->type = TTY_DRIVER_TYPE_SERIAL; tty_sample_driver->subtype = SERIAL_TYPE_NORMAL; tty_sample_driver->init_termios = tty_std_termios; tty_set_operations(tty_sample_driver, &tty_sample_ops); ret = tty_register_driver(tty_sample_driver); if (ret) { put_tty_driver(tty_sample_driver); return ret; } hrtimer_init(&emu_kbd_desc,CLOCK_MONOTONIC,HRTIMER_MODE_REL); emu_kbd_desc.function = emu_keyboard; printk("tty_sample: initialized\n"); return 0; } static void __exit mod_exit(void) { hrtimer_cancel( &emu_kbd_desc ); tty_unregister_driver(tty_sample_driver); put_tty_driver(tty_sample_driver); } module_init( mod_init ); module_exit( mod_exit ); MODULE_LICENSE("GPL");