【 以下文字转载自 Programming 讨论区 】 发信人: isup (No), 信区: Programming 标 题: 哪位用过tty_flip_buffer_push()? 发信站: BBS 未名空间站 (Sun Jun 15 17:43:46 2014, 美东) I am trying to run tiny_tty in LDD3. When I use "cat /dev/ttty0" to read from it, there is no output and the command is blocked. Checking the trace, I notice both tty_insert_flip_char() and tty_flip_buffer _push() are called. However, the data is not sent to the user by tty core. Instead, it is sent back to the tiny_tty driver's tiny_write() callback function. What is wrong there? The kernel version is 2.6.32-61-generic. static void tiny_timer(unsigned long timer_data) { struct tiny_serial *tiny = (struct tiny_serial *)timer_data; struct tty_struct *tty_st_p; struct tty_port *port; int i; char data[1] = {TINY_DATA_CHARACTER}; int data_size = 1; if (!tiny) return; tty_st_p = tiny->tty_tse_p; if (!tty_buffer_request_room(tty_st_p, 1)) tty_flip_buffer_push(tty_st_p); tty_insert_flip_char(tty_st_p, 'H', TTY_NORMAL); tty_flip_buffer_push(tty_st_p); printk(KERN_INFO "tiny_timer() tty_flip_buffer_push()n"); /* resubmit the timer again */ tiny->timer->expires = jiffies + DELAY_TIME; add_timer(tiny->timer); } static int tiny_open(struct tty_struct *tty_st_p, struct file *file) { struct tiny_serial *tiny; struct timer_list *timer; int index; /* initialize the pointer in case something fails */ tty_st_p->driver_data = NULL; /* get the serial object associated with this tty pointer */ index = tty_st_p->index; tiny = tiny_table[index]; if (tiny == NULL) { /* first time accessing this device, let's create it */ tiny = kmalloc(sizeof(*tiny), GFP_KERNEL); if (!tiny) return -ENOMEM; sema_init(&tiny->sem, 1); tiny->open_count = 0; tiny->timer = NULL; tiny_table[index] = tiny; } down(&tiny->sem); /* save our structure within the tty structure */ tty_st_p->driver_data = tiny; tiny->tty_tse_p = tty_st_p; ++tiny->open_count; if (tiny->open_count == 1) { /* this is the first time this port is opened */ /* do any hardware initialization needed here */ /* create our timer and submit it */ if (!tiny->timer) { timer = kmalloc(sizeof(*timer), GFP_KERNEL); if (!timer) { up(&tiny->sem); return -ENOMEM; } tiny->timer = timer; init_timer(tiny->timer); } tiny->timer->data = (unsigned long )tiny; tiny->timer->expires = jiffies + DELAY_TIME; tiny->timer->function = tiny_timer; printk(KERN_INFO, "tiny_open()n"); add_timer(tiny->timer); } up(&tiny->sem); return 0; } static int tiny_write(struct tty_struct *tty_st_p, const unsigned char *buffer, int count) { struct tiny_serial *tiny = tty_st_p->driver_data; int i; int retval = -EINVAL; if (!tiny) return -ENODEV; down(&tiny->sem); if (!tiny->open_count) /* port was not opened */ goto exit; /* fake sending the data out a hardware port by * writing it to the kernel debug log. */ printk(KERN_DEBUG "%s - ", __FUNCTION__); for (i = 0; i < count; ++i) printk("%02x ", buffer[i]); printk("n"); retval = count; exit: up(&tiny->sem); return retval; }