📄 mem_tty.c
字号:
if (!mem->timer) { timer = kmalloc (sizeof (*timer), GFP_KERNEL); if (!timer) { --mem->open_count; up (&mem->sem); MOD_DEC_USE_COUNT; return -ENOMEM; } mem->timer = timer; } init_timer (mem->timer); mem->timer->data = (unsigned long )mem; mem->timer->function = mem_tty_timer; // mem->timer->expires = jiffies + DELAY_TIME; // add_timer (mem->timer); } up (&mem->sem); return 0;}static void do_close (struct mem_tty_serial *mem){ down (&mem->sem); if (!mem->open_count) { /* port was never opened */ return; } --mem->open_count; if (mem->open_count <= 0) { /* The port is being closed by the last user. */ /* Do any hardware specific stuff here */ /* shut down our timer */ /* N.B. The timer memory is not kfree'd */ del_timer (mem->timer); } MOD_DEC_USE_COUNT; up (&mem->sem);}static void mem_tty_close (struct tty_struct *tty, struct file * filp){ struct mem_tty_serial *mem = tty->driver_data; if ( !mem ) { return; } do_close (mem);} static int mem_tty_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count){ struct mem_tty_serial *mem = tty->driver_data; int retval = -EINVAL; int c, c1; unsigned char * tmp_buf = NULL; if ( ! mem ) return -ENODEV; down (&mem->sem); if (!mem->open_count) { /* port was not opened */ up (&mem->sem); return -EINVAL; } if ( mem->throttling ) { up (&mem->sem); return -EAGAIN; } if ( from_user ) { if ( mem->head >= mem->tail ) { if ( mem->head == MEM_HW_SIZE-1 && mem->tail == 0 ) { up(&mem->sem); return -EAGAIN; } if ( count > MEM_HW_SIZE - mem->head) count = MEM_HW_SIZE - mem->head; } else { if ( mem->head == mem->tail-1 ) { up(&mem->sem); return -EAGAIN; } if ( count > mem->tail-1 - mem->head ) count = mem->tail-1 - mem->head; } retval = count; /* now send the data out the harware port */ tmp_buf = kmalloc( count, GFP_KERNEL ); if ( tmp_buf == NULL ) { up(&mem->sem); return -ENOMEM; } memset( tmp_buf, 0, count); copy_from_user( tmp_buf, buf, count); c1 = mem->head; // current writing head for (c=0; c<count; c++) { mem->hw_buffer[c1] = tmp_buf[c]; c1 = (c1+1) % MEM_HW_SIZE; } if ( mem->head == mem->tail ) { // queue read() printk(KERN_ALERT "mem_tty_write submit timer \n"); mem->timer->expires = jiffies + DELAY_TIME; add_timer (mem->timer); } mem->head = c1; // next position to write kfree( tmp_buf ); } else { // nothing much to do when the data come from the kernel printk(KERN_ALERT "mem_tty_write from_kernel count %d %x\n", count, buf[0] ); retval = count; } up(&mem->sem); // printk(KERN_ALERT "mem_tty_write from_user %d count %d return %d\n", // from_user, count, retval); return retval;}static void mem_tty_throttle(struct tty_struct *tty){ struct mem_tty_serial *mem = tty->driver_data; if (!mem) return; down (&mem->sem); if (!mem->open_count) { /* port was not opened */ up (&mem->sem); return; } del_timer (mem->timer); mem->throttling = 1; up (&mem->sem);}static void mem_tty_unthrottle(struct tty_struct *tty){ struct mem_tty_serial *mem = tty->driver_data; if (!mem) return down (&mem->sem); if (!mem->open_count) { /* port was not opened */ up (&mem->sem); return; } mem->throttling = 0; if ( mem->head == mem->tail ) { // queue read() printk(KERN_ALERT "mem_tty_unthrottle submit timer \n"); mem->timer->expires = jiffies + DELAY_TIME; add_timer (mem->timer); } up (&mem->sem);} static void mem_tty_flush_chars (struct tty_struct *tty) { // struct mem_tty_serial *mem = tty->driver_data; return;}static int mem_tty_chars_in_buffer(struct tty_struct *tty){ struct mem_tty_serial *mem = tty->driver_data; int chars; if (!mem) return -ENODEV; down (&mem->sem); if (!mem->open_count) { /* port was not opened */ up (&mem->sem); return -EINVAL; } if ( mem->head >= mem->tail ) { chars = mem->head - mem->tail; } else { chars = MEM_HW_SIZE - mem->tail + mem->head; } up (&mem->sem); if ( chars > 0 ) printk(KERN_ALERT "mem_tty_chars_in_buffer chars %d\n", chars); return chars;}static int mem_tty_write_room (struct tty_struct *tty) { struct mem_tty_serial *mem = tty->driver_data; int room; if (!mem) return -ENODEV; down (&mem->sem); if (!mem->open_count) { /* port was not opened */ up (&mem->sem); return -EINVAL; } /* calculate how much room is left in the device */ if ( mem->head >= mem->tail ) { room = MEM_HW_SIZE - mem->head + mem->tail - 1; } else { room = mem->tail-1 - mem->head; } up (&mem->sem); if ( room > 0 ) printk(KERN_ALERT "mem_tty_write_room room %d\n", room); return room;}static struct tty_driver mem_tty_driver = { magic: TTY_DRIVER_MAGIC, driver_name: "mem_tty",#ifndef CONFIG_DEVFS_FS name: "ttty",#else name: "tts/ttty%d",#endif major: MEM_TTY_MAJOR, num: MEM_TTY_MINORS, type: TTY_DRIVER_TYPE_SERIAL, subtype: SERIAL_TYPE_NORMAL, flags: TTY_DRIVER_REAL_RAW, refcount: &mem_tty_refcount, table: mem_tty, termios: mem_tty_termios, termios_locked: mem_tty_termios_locked, open: mem_tty_open, close: mem_tty_close, write: mem_tty_write, write_room: mem_tty_write_room, ioctl: mem_tty_ioctl, throttle: mem_tty_throttle, unthrottle: mem_tty_unthrottle, flush_chars: mem_tty_flush_chars, chars_in_buffer: mem_tty_chars_in_buffer,};static int __init mem_tty_init(void){ /* register the tty driver */ mem_tty_driver.init_termios = tty_std_termios; mem_tty_driver.init_termios.c_lflag &= ~( ECHO ); mem_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; mem_tty_driver.init_termios.c_oflag &= ~( OPOST ); mem_tty_driver.init_termios.c_cc[VMIN] = 1; mem_tty_driver.init_termios.c_cc[VTIME] = 0; if (tty_register_driver (&mem_tty_driver)) { printk (KERN_ERR "failed to register mem tty driver\n"); return -1; } printk (KERN_INFO DRIVER_DESC " " DRIVER_VERSION "\n"); return 0;}static void __exit mem_tty_exit(void){ struct mem_tty_serial *mem; int i; tty_unregister_driver(&mem_tty_driver); /* shut down all of the timers and free the memory */ for (i = 0; i < MEM_TTY_MINORS; ++i) { mem = mem_tty_table[i]; if (mem) { /* close the port */ while (mem->open_count) do_close (mem); /* shut down our timer and free the memory */ del_timer (mem->timer); kfree (mem->timer); kfree( mem->hw_buffer ); kfree (mem); mem_tty_table[i] = NULL; } }}module_init(mem_tty_init);module_exit(mem_tty_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -