关于tty这部分请参考:

《Linux设备驱动开发详解 第二版》第14章 Linux终端设备驱动

《精通Linux设备驱动程序开发》第6章 串行设备驱动程序

《Linux设备驱动程序 第三版》第18章 TTY驱动程序

下面是一些串口相关的文档:

http://pan.baidu.com/s/1mg20Umc

Makefile:

# Comment/uncomment the following line to disable/enable debugging
#DEBUG = y# Add your debugging flag (or not) to CFLAGS
ifeq ($(DEBUG),y)DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
elseDEBFLAGS = -O2
endifEXTRA_CFLAGS += $(DEBFLAGS)
EXTRA_CFLAGS += -I..ifneq ($(KERNELRELEASE),)
# call from kernel build systemobj-m    := tiny_tty.o tiny_serial.oelse#KERNELDIR ?= /lib/modules/$(shell uname -r)/build
KERNELDIR ?= /root/Tiny4412_android_4_1_2/linux-3.0.31
PWD       := $(shell pwd)default:$(MAKE) -C $(KERNELDIR) M=$(PWD) modulesendifclean:rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versionsdepend .depend dep:$(CC) $(EXTRA_CFLAGS) -M *.c > .dependifeq (.depend,$(wildcard .depend))
include .depend
endif

tiny_tty.c

/** Tiny TTY driver** Copyright (C) 2002-2004 Greg Kroah-Hartman (greg@kroah.com)**    This program is free software; you can redistribute it and/or modify*    it under the terms of the GNU General Public License as published by*    the Free Software Foundation, version 2 of the License.** This driver shows how to create a minimal tty driver.  It does not rely on* any backing hardware, but creates a timer that emulates data being received* from some kind of hardware.*/#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/sched.h>
#include <linux/seq_file.h>
#include <asm/uaccess.h>#define DRIVER_VERSION "v2.0"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
#define DRIVER_DESC "Tiny TTY driver"/* Module information */
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_LICENSE("GPL");#define DELAY_TIME        HZ * 2    /* 2 seconds per character */
#define TINY_DATA_CHARACTER    't'#define TINY_TTY_MAJOR        240    /* experimental range */
#define TINY_TTY_MINORS        4    /* only have 4 devices */struct tiny_serial {struct tty_struct    *tty;        /* pointer to the tty for this device */int            open_count;    /* number of times this port has been opened */struct semaphore    sem;        /* locks this structure */struct timer_list    *timer;/* for tiocmget and tiocmset functions */int            msr;        /* MSR shadow */int            mcr;        /* MCR shadow *//* for ioctl fun */struct serial_struct    serial;wait_queue_head_t    wait;struct async_icount    icount;
};static struct tiny_serial *tiny_table[TINY_TTY_MINORS];    /* initially all NULL */static void tiny_timer(unsigned long timer_data)
{struct tiny_serial *tiny = (struct tiny_serial *)timer_data;struct tty_struct *tty;int i;char data[1] = {TINY_DATA_CHARACTER};int data_size = 1;if (!tiny)return;tty = tiny->tty;/* send the data to the tty layer for users to read.  This doesn't* actually push the data through unless tty->low_latency is set */for (i = 0; i < data_size; ++i) {if (!tty_buffer_request_room(tty, 1))tty_flip_buffer_push(tty);tty_insert_flip_char(tty, data[i], TTY_NORMAL);}tty_flip_buffer_push(tty);/* resubmit the timer again */tiny->timer->expires = jiffies + DELAY_TIME;add_timer(tiny->timer);
}static int tiny_open(struct tty_struct *tty, struct file *file)
{struct tiny_serial *tiny;struct timer_list *timer;int index;/* initialize the pointer in case something fails */tty->driver_data = NULL;/* get the serial object associated with this tty pointer */index = tty->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->driver_data = tiny;tiny->tty = tty;++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;add_timer(tiny->timer);}up(&tiny->sem);return 0;
}static void do_close(struct tiny_serial *tiny)
{down(&tiny->sem);if (!tiny->open_count) {/* port was never opened */goto exit;}--tiny->open_count;if (tiny->open_count <= 0) {/* The port is being closed by the last user. *//* Do any hardware specific stuff here *//* shut down our timer */del_timer(tiny->timer);}
exit:up(&tiny->sem);
}static void tiny_close(struct tty_struct *tty, struct file *file)
{struct tiny_serial *tiny = tty->driver_data;if (tiny)do_close(tiny);
}    static int tiny_write(struct tty_struct *tty, const unsigned char *buffer, int count)
{struct tiny_serial *tiny = tty->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");exit:up(&tiny->sem);return retval;
}static int tiny_write_room(struct tty_struct *tty)
{struct tiny_serial *tiny = tty->driver_data;int room = -EINVAL;if (!tiny)return -ENODEV;down(&tiny->sem);if (!tiny->open_count) {/* port was not opened */goto exit;}/* calculate how much room is left in the device */room = 255;exit:up(&tiny->sem);return room;
}#define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))static void tiny_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{unsigned int cflag;cflag = tty->termios->c_cflag;/* check that they really want us to change something */if (old_termios) {if ((cflag == old_termios->c_cflag) &&(RELEVANT_IFLAG(tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {printk(KERN_DEBUG " - nothing to change...\n");return;}}/* get the byte size */switch (cflag & CSIZE) {case CS5:printk(KERN_DEBUG " - data bits = 5\n");break;case CS6:printk(KERN_DEBUG " - data bits = 6\n");break;case CS7:printk(KERN_DEBUG " - data bits = 7\n");break;default:case CS8:printk(KERN_DEBUG " - data bits = 8\n");break;}/* determine the parity */if (cflag & PARENB)if (cflag & PARODD)printk(KERN_DEBUG " - parity = odd\n");elseprintk(KERN_DEBUG " - parity = even\n");elseprintk(KERN_DEBUG " - parity = none\n");/* figure out the stop bits requested */if (cflag & CSTOPB)printk(KERN_DEBUG " - stop bits = 2\n");elseprintk(KERN_DEBUG " - stop bits = 1\n");/* figure out the hardware flow control settings */if (cflag & CRTSCTS)printk(KERN_DEBUG " - RTS/CTS is enabled\n");elseprintk(KERN_DEBUG " - RTS/CTS is disabled\n");/* determine software flow control *//* if we are implementing XON/XOFF, set the start and * stop character in the device */if (I_IXOFF(tty) || I_IXON(tty)) {unsigned char stop_char  = STOP_CHAR(tty);unsigned char start_char = START_CHAR(tty);/* if we are implementing INBOUND XON/XOFF */if (I_IXOFF(tty))printk(KERN_DEBUG " - INBOUND XON/XOFF is enabled, ""XON = %2x, XOFF = %2x", start_char, stop_char);elseprintk(KERN_DEBUG" - INBOUND XON/XOFF is disabled");/* if we are implementing OUTBOUND XON/XOFF */if (I_IXON(tty))printk(KERN_DEBUG" - OUTBOUND XON/XOFF is enabled, ""XON = %2x, XOFF = %2x", start_char, stop_char);elseprintk(KERN_DEBUG" - OUTBOUND XON/XOFF is disabled");}/* get the baud rate wanted */printk(KERN_DEBUG " - baud rate = %d", tty_get_baud_rate(tty));
}/* Our fake UART values */
#define MCR_DTR        0x01
#define MCR_RTS        0x02
#define MCR_LOOP    0x04
#define MSR_CTS        0x08
#define MSR_CD        0x10
#define MSR_RI        0x20
#define MSR_DSR        0x40static int tiny_tiocmget(struct tty_struct *tty)
{struct tiny_serial *tiny = tty->driver_data;unsigned int result = 0;unsigned int msr = tiny->msr;unsigned int mcr = tiny->mcr;result = ((mcr & MCR_DTR)  ? TIOCM_DTR  : 0) |    /* DTR is set */((mcr & MCR_RTS)  ? TIOCM_RTS  : 0) |    /* RTS is set */((mcr & MCR_LOOP) ? TIOCM_LOOP : 0) |    /* LOOP is set */((msr & MSR_CTS)  ? TIOCM_CTS  : 0) |    /* CTS is set */((msr & MSR_CD)   ? TIOCM_CAR  : 0) |    /* Carrier detect is set*/((msr & MSR_RI)   ? TIOCM_RI   : 0) |    /* Ring Indicator is set */((msr & MSR_DSR)  ? TIOCM_DSR  : 0);    /* DSR is set */return result;
}static int tiny_tiocmset(struct tty_struct *tty, unsigned int set,unsigned int clear)
{struct tiny_serial *tiny = tty->driver_data;unsigned int mcr = tiny->mcr;if (set & TIOCM_RTS)mcr |= MCR_RTS;if (set & TIOCM_DTR)mcr |= MCR_RTS;if (clear & TIOCM_RTS)mcr &= ~MCR_RTS;if (clear & TIOCM_DTR)mcr &= ~MCR_RTS;/* set the new MCR value in the device */tiny->mcr = mcr;return 0;
}static int tiny_proc_show(struct seq_file *m, void *v)
{struct tiny_serial *tiny;int i;seq_printf(m, "tinyserinfo:1.0 driver:%s\n", DRIVER_VERSION);for (i = 0; i < TINY_TTY_MINORS; ++i) {tiny = tiny_table[i];if (tiny == NULL)continue;seq_printf(m, "%d\n", i);}return 0;
}#define tiny_ioctl tiny_ioctl_tiocgserial
static int tiny_ioctl(struct tty_struct *tty, unsigned int cmd,unsigned long arg)
{struct tiny_serial *tiny = tty->driver_data;if (cmd == TIOCGSERIAL) {struct serial_struct tmp;if (!arg)return -EFAULT;memset(&tmp, 0, sizeof(tmp));tmp.type        = tiny->serial.type;tmp.line        = tiny->serial.line;tmp.port        = tiny->serial.port;tmp.irq            = tiny->serial.irq;tmp.flags        = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;tmp.xmit_fifo_size    = tiny->serial.xmit_fifo_size;tmp.baud_base        = tiny->serial.baud_base;tmp.close_delay        = 5*HZ;tmp.closing_wait    = 30*HZ;tmp.custom_divisor    = tiny->serial.custom_divisor;tmp.hub6        = tiny->serial.hub6;tmp.io_type        = tiny->serial.io_type;if (copy_to_user((void __user *)arg, &tmp, sizeof(struct serial_struct)))return -EFAULT;return 0;}return -ENOIOCTLCMD;
}
#undef tiny_ioctl#define tiny_ioctl tiny_ioctl_tiocmiwait
static int tiny_ioctl(struct tty_struct *tty, unsigned int cmd,unsigned long arg)
{struct tiny_serial *tiny = tty->driver_data;if (cmd == TIOCMIWAIT) {DECLARE_WAITQUEUE(wait, current);struct async_icount cnow;struct async_icount cprev;cprev = tiny->icount;while (1) {add_wait_queue(&tiny->wait, &wait);set_current_state(TASK_INTERRUPTIBLE);schedule();remove_wait_queue(&tiny->wait, &wait);/* see if a signal woke us up */if (signal_pending(current))return -ERESTARTSYS;cnow = tiny->icount;if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)return -EIO; /* no change => error */if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {return 0;}cprev = cnow;}}return -ENOIOCTLCMD;
}
#undef tiny_ioctl#define tiny_ioctl tiny_ioctl_tiocgicount
static int tiny_ioctl(struct tty_struct *tty, unsigned int cmd,unsigned long arg)
{struct tiny_serial *tiny = tty->driver_data;if (cmd == TIOCGICOUNT) {struct async_icount cnow = tiny->icount;struct serial_icounter_struct icount;icount.cts    = cnow.cts;icount.dsr    = cnow.dsr;icount.rng    = cnow.rng;icount.dcd    = cnow.dcd;icount.rx    = cnow.rx;icount.tx    = cnow.tx;icount.frame    = cnow.frame;icount.overrun    = cnow.overrun;icount.parity    = cnow.parity;icount.brk    = cnow.brk;icount.buf_overrun = cnow.buf_overrun;if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))return -EFAULT;return 0;}return -ENOIOCTLCMD;
}
#undef tiny_ioctl/* the real tiny_ioctl function.  The above is done to get the small functions in the book */
static int tiny_ioctl(struct tty_struct *tty, unsigned int cmd,unsigned long arg)
{switch (cmd) {case TIOCGSERIAL:return tiny_ioctl_tiocgserial(tty, cmd, arg);case TIOCMIWAIT:return tiny_ioctl_tiocmiwait(tty, cmd, arg);case TIOCGICOUNT:return tiny_ioctl_tiocgicount(tty, cmd, arg);}return -ENOIOCTLCMD;
}static int tiny_proc_open(struct inode *inode, struct file *file)
{return single_open(file, tiny_proc_show, NULL);
}static const struct file_operations serial_proc_fops = {.owner          = THIS_MODULE,.open           = tiny_proc_open,.read           = seq_read,.llseek         = seq_lseek,.release        = single_release,
};static struct tty_operations serial_ops = {.open = tiny_open,.close = tiny_close,.write = tiny_write,.write_room = tiny_write_room,.set_termios = tiny_set_termios,.proc_fops    = &serial_proc_fops,.tiocmget = tiny_tiocmget,.tiocmset = tiny_tiocmset,.ioctl = tiny_ioctl,
};static struct tty_driver *tiny_tty_driver;static int __init tiny_init(void)
{int retval;int i;/* allocate the tty driver */tiny_tty_driver = alloc_tty_driver(TINY_TTY_MINORS);if (!tiny_tty_driver)return -ENOMEM;/* initialize the tty driver */tiny_tty_driver->owner = THIS_MODULE;tiny_tty_driver->driver_name = "tiny_tty";tiny_tty_driver->name = "ttty";tiny_tty_driver->major = TINY_TTY_MAJOR,tiny_tty_driver->type = TTY_DRIVER_TYPE_SERIAL,tiny_tty_driver->subtype = SERIAL_TYPE_NORMAL,tiny_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV,tiny_tty_driver->init_termios = tty_std_termios;tiny_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;tty_set_operations(tiny_tty_driver, &serial_ops);/* register the tty driver */retval = tty_register_driver(tiny_tty_driver);if (retval) {printk(KERN_ERR "failed to register tiny tty driver");put_tty_driver(tiny_tty_driver);return retval;}for (i = 0; i < TINY_TTY_MINORS; ++i)tty_register_device(tiny_tty_driver, i, NULL);printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION);return retval;
}static void __exit tiny_exit(void)
{struct tiny_serial *tiny;int i;for (i = 0; i < TINY_TTY_MINORS; ++i)tty_unregister_device(tiny_tty_driver, i);tty_unregister_driver(tiny_tty_driver);/* shut down all of the timers and free the memory */for (i = 0; i < TINY_TTY_MINORS; ++i) {tiny = tiny_table[i];if (tiny) {/* close the port */while (tiny->open_count)do_close(tiny);/* shut down our timer and free the memory */del_timer(tiny->timer);kfree(tiny->timer);kfree(tiny);tiny_table[i] = NULL;}}
}module_init(tiny_init);
module_exit(tiny_exit);

tiny_serial.c

/** Tiny Serial driver** Copyright (C) 2002-2004 Greg Kroah-Hartman (greg@kroah.com)**    This program is free software; you can redistribute it and/or modify*    it under the terms of the GNU General Public License as published by*    the Free Software Foundation, version 2 of the License.** This driver shows how to create a minimal serial driver.  It does not rely on* any backing hardware, but creates a timer that emulates data being received* from some kind of hardware.*/#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <linux/module.h>#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
#define DRIVER_DESC "Tiny serial driver"/* Module information */
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_LICENSE("GPL");#define DELAY_TIME        HZ * 2    /* 2 seconds per character */
#define TINY_DATA_CHARACTER    't'#define TINY_SERIAL_MAJOR    240    /* experimental range */
#define TINY_SERIAL_MINORS    1    /* only have one minor */
#define UART_NR            1    /* only use one port */#define TINY_SERIAL_NAME    "ttytiny"#define MY_NAME            TINY_SERIAL_NAMEstatic struct timer_list *timer;static void tiny_stop_tx(struct uart_port *port)
{
}static void tiny_stop_rx(struct uart_port *port)
{
}static void tiny_enable_ms(struct uart_port *port)
{
}static void tiny_tx_chars(struct uart_port *port)
{struct circ_buf *xmit = &port->state->xmit;int count;if (port->x_char) {pr_debug("wrote %2x", port->x_char);port->icount.tx++;port->x_char = 0;return;}if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {tiny_stop_tx(port);return;}count = port->fifosize >> 1;do {pr_debug("wrote %2x", xmit->buf[xmit->tail]);xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);port->icount.tx++;if (uart_circ_empty(xmit))break;} while (--count > 0);if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)uart_write_wakeup(port);if (uart_circ_empty(xmit))tiny_stop_tx(port);
}static void tiny_start_tx(struct uart_port *port)
{
}static void tiny_timer(unsigned long data)
{struct uart_port *port;struct tty_struct *tty;port = (struct uart_port *)data;if (!port)return;if (!port->state)return;tty = port->state->port.tty;if (!tty)return;/* add one character to the tty port *//* this doesn't actually push the data through unless tty->low_latency is set */tty_insert_flip_char(tty, TINY_DATA_CHARACTER, 0);tty_flip_buffer_push(tty);/* resubmit the timer again */timer->expires = jiffies + DELAY_TIME;add_timer(timer);/* see if we have any data to transmit */tiny_tx_chars(port);
}static unsigned int tiny_tx_empty(struct uart_port *port)
{return 0;
}static unsigned int tiny_get_mctrl(struct uart_port *port)
{return 0;
}static void tiny_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
}static void tiny_break_ctl(struct uart_port *port, int break_state)
{
}static void tiny_set_termios(struct uart_port *port,struct ktermios *new, struct ktermios *old)
{int baud, quot, cflag = new->c_cflag;/* get the byte size */switch (cflag & CSIZE) {case CS5:printk(KERN_DEBUG " - data bits = 5\n");break;case CS6:printk(KERN_DEBUG " - data bits = 6\n");break;case CS7:printk(KERN_DEBUG " - data bits = 7\n");break;default: // CS8printk(KERN_DEBUG " - data bits = 8\n");break;}/* determine the parity */if (cflag & PARENB)if (cflag & PARODD)pr_debug(" - parity = odd\n");elsepr_debug(" - parity = even\n");elsepr_debug(" - parity = none\n");/* figure out the stop bits requested */if (cflag & CSTOPB)pr_debug(" - stop bits = 2\n");elsepr_debug(" - stop bits = 1\n");/* figure out the flow control settings */if (cflag & CRTSCTS)pr_debug(" - RTS/CTS is enabled\n");elsepr_debug(" - RTS/CTS is disabled\n");/* Set baud rate */baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16);quot = uart_get_divisor(port, baud);//UART_PUT_DIV_LO(port, (quot & 0xff));//UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
}static int tiny_startup(struct uart_port *port)
{/* this is the first time this port is opened *//* do any hardware initialization needed here *//* create our timer and submit it */if (!timer) {timer = kmalloc(sizeof(*timer), GFP_KERNEL);if (!timer)return -ENOMEM;}init_timer(timer);timer->data = (unsigned long)port;timer->expires = jiffies + DELAY_TIME;timer->function = tiny_timer;add_timer(timer);return 0;
}static void tiny_shutdown(struct uart_port *port)
{/* The port is being closed by the last user. *//* Do any hardware specific stuff here *//* shut down our timer */del_timer(timer);
}static const char *tiny_type(struct uart_port *port)
{return "tinytty";
}static void tiny_release_port(struct uart_port *port)
{}static int tiny_request_port(struct uart_port *port)
{return 0;
}static void tiny_config_port(struct uart_port *port, int flags)
{
}static int tiny_verify_port(struct uart_port *port, struct serial_struct *ser)
{return 0;
}static struct uart_ops tiny_ops = {.tx_empty    = tiny_tx_empty,.set_mctrl    = tiny_set_mctrl,.get_mctrl    = tiny_get_mctrl,.stop_tx    = tiny_stop_tx,.start_tx    = tiny_start_tx,.stop_rx    = tiny_stop_rx,.enable_ms    = tiny_enable_ms,.break_ctl    = tiny_break_ctl,.startup    = tiny_startup,.shutdown    = tiny_shutdown,.set_termios    = tiny_set_termios,.type        = tiny_type,.release_port    = tiny_release_port,.request_port    = tiny_request_port,.config_port    = tiny_config_port,.verify_port    = tiny_verify_port,
};static struct uart_port tiny_port = {.ops        = &tiny_ops,
};static struct uart_driver tiny_reg = {.owner        = THIS_MODULE,.driver_name    = TINY_SERIAL_NAME,.dev_name    = TINY_SERIAL_NAME,.major        = TINY_SERIAL_MAJOR,.minor        = TINY_SERIAL_MINORS,.nr        = UART_NR,
};static int __init tiny_init(void)
{int result;printk(KERN_INFO "Tiny serial driver loaded\n");result = uart_register_driver(&tiny_reg);if (result)return result;result = uart_add_one_port(&tiny_reg, &tiny_port);if (result)uart_unregister_driver(&tiny_reg);return result;
}module_init(tiny_init);

转载于:https://www.cnblogs.com/pengdonglin137/p/4321936.html

tiny4412 串口驱动分析五 --- LDD3上TTY驱动程序源码相关推荐

  1. tiny4412 串口驱动分析九 --- shell终端

    作者:彭东林 邮箱:pengdonglin137@163.com 开发板:tiny4412ADK+S700 4GB Flash 主机:Wind7 64位 虚拟机:Vmware+Ubuntu12_04 ...

  2. linux串口驱动分析

    linux串口驱动分析 硬件资源及描写叙述 s3c2440A 通用异步接收器和发送器(UART)提供了三个独立的异步串行 I/O(SIO)port,每一个port都能够在中断模式或 DMA 模式下操作 ...

  3. wince串口驱动分析(转)

    wince串口驱动分析 串行通讯接口主要是指UART(通用串行)和IRDA两种.通常的串行连接电气连接上有3wire和9wire两种.3wire的接线方式下定义了发送.接收和地三根连接.其用途就如名称 ...

  4. linux tty core code,linux tty core 源码分析(7)

    套接字和终端通常都具有异步通知机制,即应用程序可以在数据可用的时候接收到一个信号SIGIO而不需要去轮询关注的数据.但是当对于多个数据源时,应用不能区分SIGIO的来源.为了实现异步通知机制,应用程序 ...

  5. Android上百实例源码分析以及开源分析集合打包

    感谢网友banketree的收集,压缩包的内容如下: 1.360新版特性界面源代码 实现了360新版特性界面的效果,主要涉及到Qt的一些事件处理与自定义控件.但源码好像是c++. 2.aidl跨进程调 ...

  6. Linux内核学习(五):linux kernel源码结构以及makefile分析

    Linux内核学习(五):linux kernel源码结构以及makefile分析 前面我们知道了linux内核镜像的生成.加载以及加载工具uboot. 这里我们来看看linux内核的源码的宏观东西, ...

  7. 小程序 多张图片上传(源码分享+实现分析)

    本篇文章以小程序中的代表[微信小程序]为例,分享一下在微信小程序中实现多图上传的源码实现. PS:其它小程序 和 uni-app 也可通用该思路实现. 代码片段(可导入微信WEB开发者工具体验):ht ...

  8. Linux虚拟化KVM-Qemu分析(三)之KVM源码(1)kvm_init

    Table of Contents 1. 概述 2. KVM初始化 2.1 kvm_arch_init 2.1.1 init_hyp_mode 2.1.2 init_subsystems 2.2 mi ...

  9. 深度分析 Java 的 ClassLoader 机制(源码级别)(转)

    写在前面:Java中的所有类,必须被装载到jvm中才能运行,这个装载工作是由jvm中的类装载器完成的,类装载器所做的工作实质是把类文件从硬盘读取到内存中,JVM在加载类的时候,都是通过ClassLoa ...

  10. 深度分析Java的ClassLoader机制(源码级别)

    转载自 深度分析Java的ClassLoader机制(源码级别) Java中的所有类,必须被装载到jvm中才能运行,这个装载工作是由jvm中的类装载器完成的,类装载器所做的工作实质是把类文件从硬盘读取 ...

最新文章

  1. 自定义分辨率软件_苹果剪辑软件Final Cut Pro X导出竖屏视频教程
  2. 3D打印机分类与速度
  3. [云炬创业管理笔记]第十章商业计划书答辩测试2
  4. VC2008的运行库问题。
  5. linux 进程与锁,linux 中的进程与锁
  6. python中的ix是啥_python pandas (ix iloc loc) 的区别
  7. JavaScript中如何自定义属性操作
  8. SpringBoot+Vue项目上手
  9. 给 Java 说句公道话
  10. 下载npm并配置npm环境
  11. VMware14秘钥
  12. 适合于图像处理方向的SCI期刊杂志列表
  13. ROG GL552VW BIOS 编程器官方固件
  14. 数据结构试卷及答案(七)
  15. Win:在 Windows Server 中的 NIC Teaming
  16. PS学习笔记(88天和我一起学会PS)(5/88)
  17. 怎么在HTML中加入热区,关于网页点击热区图
  18. python 正则表达式匹配
  19. Uniapp离线打包使用高德地图教程及常见问题
  20. USACO 1月 2021-2022 January Contest Silver银组 题解

热门文章

  1. CentOS6.2安装LAMP+DRUPAL网站(1)
  2. 思科和华为交换机常用命令对比学习
  3. IT公司是怎样面试的? (转载)
  4. iOS 将本地项目/demo上传到github的简单方法
  5. 重装了新版IDEA,但我之前的个人配置全丢了,太烦了!
  6. 写这么骚的代码,真不怕被同事揍么?
  7. 厉害了!有同学抽时间整理了一份IDEA中如何使用Git进行项目管理的完整教程?...
  8. 带薪休假,运维汪的春天来了?
  9. IT人的春节对联集锦
  10. IT人是这么过圣诞的……