Chinaunix首页 | 论坛 | 博客
  • 博客访问: 734029
  • 博文数量: 192
  • 博客积分: 2653
  • 博客等级: 少校
  • 技术积分: 1623
  • 用 户 组: 普通用户
  • 注册时间: 2012-05-31 18:25
个人简介

How tough life is, how strong you should be!

文章分类

全部博文(192)

文章存档

2015年(1)

2014年(2)

2013年(37)

2012年(152)

分类: LINUX

2012-07-03 15:43:26

以下两个结构体是自定义的,代码里面有用到...

struct sam_XXX_buf_t

{

  size_t    len,

            used,

            size;

  unsigned char *ptr;

};

struct sam_XXX_tty_t

{

  struct tty_struct *tty; // pointer to the tty for this device  

  struct sam_XXX_buf_t buf;

};

主要代码如下:

#define SAM_XXX_MAX_PORT 1

static struct tty_driver  *sam_XXX_tty_driver;

static struct sam_XXX_tty_t  sam_XXX_tty;

static struct tty_operations sam_XXX_tty_ops = {

  .open             = sam_XXX_tty_open,

  .close            = sam_XXX_tty_close,

  .write            = sam_XXX_tty_write,

  .write_room       = sam_XXX_tty_write_room,

  .ioctl            = sam_XXX_tty_ioctl,

  .chars_in_buffer  = sam_XXX_tty_chars_in_buffer,

};

static int sam_XXX_tty_open (struct tty_struct *tty, struct file *file)

{

  struct sam_XXX_tty_t *tty_ptr = &sam_XXX_tty;

 

  tty->driver_data = 0;

 

  // allocate write buffer

  if (!tty_ptr->buf.ptr) {

    // TODO

  }

  tty_ptr->buf.len = 0;

  tty_ptr->tty = tty;

  tty->driver_data = tty_ptr;

  /* force low_latency on so that our tty_push actually forces the data through, 

     otherwise it is scheduled, and with high data rates (like with OHCI) data

     can get lost. */

  tty->low_latency = 1;

  printk ("sam XXX driver attached to tty #%d\n", tty->index);

  return 0;

}

static void sam_XXX_tty_close(struct tty_struct *tty, struct file * filp)

{

  struct sam_XXX_tty_t *tty_ptr;

  if (!(tty_ptr = (struct sam_XXX_tty_t *) tty->driver_data))

    return;

  tty_ptr->buf.len = 0;

  tty_ptr->tty = 0;

  tty->driver_data = 0;

  printk ("sam XXX driver detached from tty #%d\n", tty_ptr->index);

}

static int sam_XXX_tty_write (struct tty_struct * tty, const unsigned char *user_buf, int count)

{

  struct sam_XXX_tty_t *tty_ptr;

  if (!(tty_ptr = (struct sam_XXX_tty_t *) tty->driver_data))

    return -ENODEV;

  if (!count ||

      !tty_ptr->buf.size - tty_ptr->buf.len) {

    return 0;

  }

  // take the affortable length

  if (count > tty_ptr->buf.size - tty_ptr->buf.len)

    count = tty_ptr->buf.size - tty_ptr->buf.len;

  printk ("sam XXX driver tty #%d write %d bytes into module\n", tty_ptr->index, count);

  // copy data into write buffer and trigger write interrupt

  memcpy (tty_ptr->buf.ptr + tty_ptr->buf.len, user_buf, count);

  // TODO: write data to device

  return count;

}

static int sam_XXX_tty_write_room (struct tty_struct * tty)

{

  struct sam_XXX_tty_t *tty_ptr;

  if (!(tty_ptr = (struct sam_XXX_tty_t *) tty->driver_data))

    return -ENODEV;

  // tell the tty the available write buffer length

  return tty_ptr->buf.size - tty_ptr->buf.len;

}

int sam_XXX_tty_chars_in_buffer (struct tty_struct *tty)

{

  struct sam_XXX_tty_t *tty_ptr;

  if (!(tty_ptr = (struct sam_XXX_tty_t *) tty->driver_data))

    return -ENODEV;

  // tell the tty the remaining write buffer length

  return tty_ptr->buf.len;

}

static int sam_XXX_tty_ioctl (struct tty_struct *tty, unsigned int cmd, unsigned long arg)

{

//TODO

}

static int __init sam_XXX_init (void)

{

  int rv;

  memset (&sam_XXX_tty, 0, sizeof (sam_XXX_tty));

  // init the module

  // allocate the tty driver

  if (!(sam_XXX_tty_driver = alloc_tty_driver (SAM_XXX_MAX_PORT)))

    return -ENOMEM;

  // initialize the tty driver

  sam_XXX_tty_driver->owner = THIS_MODULE;

  sam_XXX_tty_driver->driver_name = SAM_XXX_DRV_NAME;

  sam_XXX_tty_driver->name = SAM_XXX_TTY_NAME;

  sam_XXX_tty_driver->major = SAM_XXX_TTY_MAJOR;

  sam_XXX_tty_driver->minor_start = SAM_XXX_TTY_MINOR_BASE;

  sam_XXX_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;

  sam_XXX_tty_driver->subtype = SERIAL_TYPE_NORMAL;

  sam_XXX_tty_driver->flags = TTY_DRIVER_REAL_RAW;

  sam_XXX_tty_driver->init_termios = tty_std_termios;

  sam_XXX_tty_driver->init_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;

  sam_XXX_tty_driver->init_termios.c_ispeed = sam_XXX_tty_driver->init_termios.c_ospeed = 115200;

  tty_set_operations (sam_XXX_tty_driver, &sam_XXX_tty_ops);

  // register tty driver

  if ((rv = tty_register_driver (sam_XXX_tty_driver))) {

    put_tty_driver (sam_XXX_tty_driver);

    return rv;

  }

  printk ("sam XXX driver v%s installed\n", SAM_XXX_DRV_VER);

  return 0;

}

static void __exit sam_XXX_exit (void)

{

  if (sam_XXX_tty_driver) {

    tty_unregister_driver (sam_XXX_tty_driver);

    put_tty_driver (sam_XXX_tty_driver);

  }

  // release hardware

  sam_XXX_hw_term ();

  printk ("sam XXX driver v%s removed\n", SAM_XXX_DRV_VER);

}

module_init (sam_XXX_init);

module_exit (sam_XXX_exit);

MODULE_LICENSE ("GPL");

tty模型中不用定义read接口函数,用户层读取的数据需要使用函数
tty_insert_flip_string 或者 tty_insert_flip_char存入数据,然后使用 tty_flip_buffer_push讲数据推送到用户层(read)

使用tty模型的驱动,用户层在open该驱动后需要初始化 struct termios,这个是必须的,否则读不到数据的...
阅读(1157) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~