⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mem_tty.c

📁 LINUX内核编程的一些程序例子
💻 C
📖 第 1 页 / 共 2 页
字号:
    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 + -