How tough life is, how strong you should be!
分类: 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");