Subversion Repositories shark

Compare Revisions

Ignore whitespace Rev 846 → Rev 1065

/shark/trunk/drivers/usb/serial/tty_io.c
1,210 → 1,319
/*
* linux/drivers/char/tty_io.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
*/
 
#include <linuxcomp.h>
 
#include <linux/config.h>
#include <linux/types.h>
#include <linux/major.h>
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/fcntl.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
#include <linux/devpts_fs.h>
#include <linux/file.h>
#include <linux/console.h>
#include <linux/timer.h>
#include <linux/ctype.h>
#include <linux/kd.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/smp_lock.h>
#include <linux/device.h>
 
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/bitops.h>
 
#include <linux/kbd_kern.h>
#include <linux/vt_kern.h>
#include <linux/selection.h>
#include <linux/devfs_fs_kernel.h>
 
#include <linux/kmod.h>
 
#undef TTY_DEBUG_HANGUP
 
#define TTY_PARANOIA_CHECK 1
#define CHECK_TTY_COUNT 1
 
struct tty_ldisc ldiscs[NR_LDISCS];
 
struct termios tty_std_termios = { /* for the benefit of tty drivers */
.c_iflag = ICRNL | IXON,
.c_oflag = OPOST | ONLCR,
.c_cflag = B38400 | CS8 | CREAD | HUPCL,
.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |
ECHOCTL | ECHOKE | IEXTEN,
.c_cc = INIT_C_CC
};
 
struct tty_driver *alloc_tty_driver(int lines)
{
struct tty_driver *driver;
 
driver = kmalloc(sizeof(struct tty_driver), GFP_KERNEL);
if (driver) {
memset(driver, 0, sizeof(struct tty_driver));
driver->magic = TTY_DRIVER_MAGIC;
driver->num = lines;
/* later we'll move allocation of tables here */
}
return driver;
}
 
void put_tty_driver(struct tty_driver *driver)
{
kfree(driver);
}
 
void tty_set_operations(struct tty_driver *driver, struct tty_operations *op)
{
driver->open = op->open;
driver->close = op->close;
driver->write = op->write;
driver->put_char = op->put_char;
driver->flush_chars = op->flush_chars;
driver->write_room = op->write_room;
driver->chars_in_buffer = op->chars_in_buffer;
driver->ioctl = op->ioctl;
driver->set_termios = op->set_termios;
driver->throttle = op->throttle;
driver->unthrottle = op->unthrottle;
driver->stop = op->stop;
driver->start = op->start;
driver->hangup = op->hangup;
driver->break_ctl = op->break_ctl;
driver->flush_buffer = op->flush_buffer;
driver->set_ldisc = op->set_ldisc;
driver->wait_until_sent = op->wait_until_sent;
driver->send_xchar = op->send_xchar;
driver->read_proc = op->read_proc;
driver->write_proc = op->write_proc;
driver->tiocmget = op->tiocmget;
driver->tiocmset = op->tiocmset;
}
 
int tty_register_driver(struct tty_driver *driver)
{
return 0;
}
 
int tty_unregister_driver(struct tty_driver *driver)
{
return 0;
}
 
void tty_register_device(struct tty_driver *driver, unsigned index,
struct device *device)
{
 
}
 
void tty_unregister_device(struct tty_driver *driver, unsigned index)
{
 
}
 
void tty_flip_buffer_push(struct tty_struct *tty)
{
printk(KERN_INFO "%c\n", *(tty->flip.char_buf_ptr -1));
}
 
static void flush_to_ldisc(void *private_)
{
 
}
 
static struct tty_struct *alloc_tty_struct(void)
{
struct tty_struct *tty;
 
tty = kmalloc(sizeof(struct tty_struct), GFP_KERNEL);
// if (tty)
// memset(tty, 0, sizeof(struct tty_struct));
return tty;
}
 
void do_tty_hangup(void *data)
{
 
}
 
/*
* This subroutine initializes a tty structure.
*/
static void initialize_tty_struct(struct tty_struct *tty)
{
memset(tty, 0, sizeof(struct tty_struct));
tty->magic = TTY_MAGIC;
tty->ldisc = ldiscs[N_TTY];
tty->pgrp = -1;
tty->flip.char_buf_ptr = tty->flip.char_buf;
tty->flip.flag_buf_ptr = tty->flip.flag_buf;
INIT_WORK(&tty->flip.work, flush_to_ldisc, tty);
init_MUTEX(&tty->flip.pty_sem);
init_waitqueue_head(&tty->write_wait);
init_waitqueue_head(&tty->read_wait);
INIT_WORK(&tty->hangup_work, do_tty_hangup, tty);
//*sema_init(&tty->atomic_read, 1);
//*sema_init(&tty->atomic_write, 1);
spin_lock_init(&tty->read_lock);
INIT_LIST_HEAD(&tty->tty_files);
INIT_WORK(&tty->SAK_work, NULL, NULL);
}
 
extern int serial_open (struct tty_struct *tty, struct file * filp);
extern int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count);
 
struct tty_struct *tty;
int serial_usbport_open(int port_number)
{
int retval;
tty = alloc_tty_struct();
if(!tty)
goto fail_no_mem;
 
initialize_tty_struct (tty);
 
tty->termios = malloc (sizeof(struct termios));
*(tty->termios) = tty_std_termios;
 
retval = serial_open(tty, NULL);
return retval;
 
fail_no_mem:
return -ENOMEM;
}
 
int serial_usbport_write(const unsigned char *buf, int count)
{
int retval;
retval = serial_write(tty, 0, buf, count);
return retval;
 
// printk(KERN_DEBUG "######### retval=%d\n", retval);
}
/*
* linux/drivers/char/tty_io.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
*/
 
#include <linuxcomp.h>
 
#include <linux/config.h>
#include <linux/types.h>
#include <linux/major.h>
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/fcntl.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
#include <linux/devpts_fs.h>
#include <linux/file.h>
#include <linux/console.h>
#include <linux/timer.h>
#include <linux/ctype.h>
#include <linux/kd.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/smp_lock.h>
#include <linux/device.h>
 
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/bitops.h>
 
#include <linux/kbd_kern.h>
#include <linux/vt_kern.h>
#include <linux/selection.h>
#include <linux/devfs_fs_kernel.h>
 
#include <linux/kmod.h>
 
#undef TTY_DEBUG_HANGUP
 
#define TTY_PARANOIA_CHECK 1
#define CHECK_TTY_COUNT 1
 
struct tty_ldisc ldiscs[NR_LDISCS];
 
struct termios tty_std_termios = { /* for the benefit of tty drivers */
.c_iflag = ICRNL | IXON,
.c_oflag = OPOST | ONLCR,
.c_cflag = B4800 | CS8 | CREAD | HUPCL,
.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |
ECHOCTL | ECHOKE | IEXTEN,
.c_cc = INIT_C_CC
};
 
struct tty_driver *alloc_tty_driver(int lines)
{
struct tty_driver *driver;
 
driver = kmalloc(sizeof(struct tty_driver), GFP_KERNEL);
if (driver) {
memset(driver, 0, sizeof(struct tty_driver));
driver->magic = TTY_DRIVER_MAGIC;
driver->num = lines;
/* later we'll move allocation of tables here */
}
return driver;
}
 
void put_tty_driver(struct tty_driver *driver)
{
kfree(driver);
}
 
void tty_set_operations(struct tty_driver *driver, struct tty_operations *op)
{
driver->open = op->open;
driver->close = op->close;
driver->write = op->write;
driver->put_char = op->put_char;
driver->flush_chars = op->flush_chars;
driver->write_room = op->write_room;
driver->chars_in_buffer = op->chars_in_buffer;
driver->ioctl = op->ioctl;
driver->set_termios = op->set_termios;
driver->throttle = op->throttle;
driver->unthrottle = op->unthrottle;
driver->stop = op->stop;
driver->start = op->start;
driver->hangup = op->hangup;
driver->break_ctl = op->break_ctl;
driver->flush_buffer = op->flush_buffer;
driver->set_ldisc = op->set_ldisc;
driver->wait_until_sent = op->wait_until_sent;
driver->send_xchar = op->send_xchar;
driver->read_proc = op->read_proc;
driver->write_proc = op->write_proc;
driver->tiocmget = op->tiocmget;
driver->tiocmset = op->tiocmset;
}
 
int tty_register_driver(struct tty_driver *driver)
{
return 0;
}
 
int tty_unregister_driver(struct tty_driver *driver)
{
return 0;
}
 
void tty_register_device(struct tty_driver *driver, unsigned index,
struct device *device)
{
 
}
 
void tty_unregister_device(struct tty_driver *driver, unsigned index)
{
 
}
 
/*
* This routine is called out of the software interrupt to flush data
* from the flip buffer to the line discipline.
*/
static void flush_to_ldisc(void *private_)
{
struct tty_struct *tty = (struct tty_struct *) private_;
unsigned char *cp;
char *fp;
int count;
 
if (tty->flip.buf_num) {
cp = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
fp = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
tty->flip.buf_num = 0;
tty->flip.char_buf_ptr = tty->flip.char_buf;
tty->flip.flag_buf_ptr = tty->flip.flag_buf;
} else {
cp = tty->flip.char_buf;
fp = tty->flip.flag_buf;
tty->flip.buf_num = 1;
tty->flip.char_buf_ptr = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
tty->flip.flag_buf_ptr = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
}
count = tty->flip.count;
tty->flip.count = 0;
 
tty->ldisc.receive_buf(tty, cp, fp, count);
}
 
 
void tty_flip_buffer_push(struct tty_struct *tty)
{
flush_to_ldisc((void *) tty);
}
 
static struct tty_struct *alloc_tty_struct(void)
{
struct tty_struct *tty;
 
tty = kmalloc(sizeof(struct tty_struct), GFP_KERNEL);
if (tty)
memset(tty, 0, sizeof(struct tty_struct));
return tty;
}
 
void do_tty_hangup(void *data)
{
 
}
 
/*
* This subroutine initializes a tty structure.
*/
static void initialize_tty_struct(struct tty_struct *tty)
{
memset(tty, 0, sizeof(struct tty_struct));
tty->magic = TTY_MAGIC;
tty->ldisc = ldiscs[N_TTY];
tty->pgrp = -1;
tty->flip.char_buf_ptr = tty->flip.char_buf;
tty->flip.flag_buf_ptr = tty->flip.flag_buf;
INIT_WORK(&tty->flip.work, flush_to_ldisc, tty);
init_MUTEX(&tty->flip.pty_sem);
init_waitqueue_head(&tty->write_wait);
init_waitqueue_head(&tty->read_wait);
INIT_WORK(&tty->hangup_work, do_tty_hangup, tty);
//*sema_init(&tty->atomic_read, 1);
//*sema_init(&tty->atomic_write, 1);
spin_lock_init(&tty->read_lock);
INIT_LIST_HEAD(&tty->tty_files);
INIT_WORK(&tty->SAK_work, NULL, NULL);
}
 
extern int serial_open (struct tty_struct *tty, struct file * filp);
extern int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count);
 
static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
{
const unsigned char *p;
char *f, flags = TTY_NORMAL;
int i;
char buf[64];
unsigned long cpuflags;
if (!tty->read_buf)
return;
 
spin_lock_irqsave(&tty->read_lock, cpuflags);
i = min(N_TTY_BUF_SIZE - tty->read_cnt, \
N_TTY_BUF_SIZE - tty->read_head);
i = min(count, i);
memcpy(tty->read_buf + tty->read_head, cp, i);
tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
tty->read_cnt += i;
spin_unlock_irqrestore(&tty->read_lock, cpuflags);
 
//** for (i=0; i<count; i++)
//** printk("%c", *(cp+i) );
}
 
/*
* Check whether to call the driver.unthrottle function.
* We test the TTY_THROTTLED bit first so that it always
* indicates the current state.
*/
static void check_unthrottle(struct tty_struct * tty)
{
if (tty->count &&
test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
tty->driver->unthrottle)
tty->driver->unthrottle(tty);
}
 
/*
* Reset the read buffer counters, clear the flags,
* and make sure the driver is unthrottled. Called
* from n_tty_open() and n_tty_flush_buffer().
*/
static void reset_buffer_flags(struct tty_struct *tty)
{
unsigned long flags;
 
spin_lock_irqsave(&tty->read_lock, flags);
tty->read_head = tty->read_tail = tty->read_cnt = 0;
spin_unlock_irqrestore(&tty->read_lock, flags);
tty->canon_head = tty->canon_data = tty->erasing = 0;
memset(&tty->read_flags, 0, sizeof tty->read_flags);
check_unthrottle(tty);
}
 
int serial_usbport_open(void **private, int port_number)
{
int retval;
struct tty_struct *tty;
tty = alloc_tty_struct();
if(!tty)
goto fail_no_mem;
 
initialize_tty_struct (tty);
 
tty->termios = kmalloc (sizeof(struct termios), GFP_KERNEL);
*(tty->termios) = tty_std_termios;
tty->index = port_number;
tty->ldisc.receive_buf = n_tty_receive_buf;
if (!tty->read_buf) {
tty->read_buf = kmalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
if (!tty->read_buf)
return -ENOMEM;
}
memset(tty->read_buf, 0, N_TTY_BUF_SIZE);
reset_buffer_flags(tty);
 
retval = serial_open(tty, NULL);
*private = (void*)tty;
return retval;
 
fail_no_mem:
return -ENOMEM;
}
 
int serial_usbport_write(void *private, const unsigned char *buf, int count)
{
int retval;
struct tty_struct *tty = (struct tty_struct*) private;
retval = serial_write(tty, 0, buf, count);
return retval;
}
 
int serial_usbport_read(void *private, char* data_in)
{
char c;
struct tty_struct *tty = (struct tty_struct*) private;
unsigned long flags;
 
if (tty->read_cnt)
{
c = tty->read_buf[tty->read_tail];
tty->read_tail = ((tty->read_tail+1) & \
(N_TTY_BUF_SIZE-1));
tty->read_cnt--;
*data_in = c;
return 1;
}
*data_in = 0;
return 0;
}