From cdad3accf23f933acdf7408c8bff92f30827f71b Mon Sep 17 00:00:00 2001 From: lyx Date: Thu, 28 Jul 2011 18:26:21 -0700 Subject: [PATCH] newton: updata irda serial driver add ioctl get frame length and start send function --- drivers/net/irda/ir_serial.c | 122 ++++++++++++++++++++++++++++------- drivers/net/irda/ir_serial.h | 18 ++++++ 2 files changed, 116 insertions(+), 24 deletions(-) diff --git a/drivers/net/irda/ir_serial.c b/drivers/net/irda/ir_serial.c index 676340e5fd03..a1c12abfcca6 100755 --- a/drivers/net/irda/ir_serial.c +++ b/drivers/net/irda/ir_serial.c @@ -21,35 +21,34 @@ #include #include #include +#include +#include #include "bu92725guw.h" +#include "ir_serial.h" struct bu92747_port { struct device *dev; struct irda_info *pdata; struct uart_port port; - - int cts; /* last CTS received for flow ctrl */ + + /*for FIR fream read*/ + unsigned long last_frame_length; + unsigned long cur_frame_length; + wait_queue_head_t data_ready_wq; + atomic_t data_ready; + int tx_empty; /* last TX empty bit */ spinlock_t conf_lock; /* shared data */ - int conf_commit; /* need to make changes */ - int conf; /* configuration for the MAX31000 - * (bits 0-7, bits 8-11 are irqs) */ - int rts_commit; /* need to change rts */ - int rts; /* rts status */ int baud; /* current baud rate */ - int parity; /* keeps track if we should send parity */ int rx_enabled; /* if we should rx chars */ int irq; /* irq assigned to the bu92747 */ int minor; /* minor number */ - int crystal; /* 1 if 3.6864Mhz crystal 0 for 1.8432 */ - int loopback; /* 1 if we are in loopback mode */ - /* for handling irqs: need workqueue since we do spi_sync */ struct workqueue_struct *workqueue; struct work_struct work; /* set to 1 to make the workhandler exit as soon as possible */ @@ -57,10 +56,6 @@ struct bu92747_port { /* need to know we are suspending to avoid deadlock on workqueue */ int suspending; - /* poll time (in ms) for ctrl lines */ - int poll_time; - /* and its timer */ - struct timer_list timer; }; #define MAX_BU92747 1 @@ -128,12 +123,14 @@ static int bu92747_irda_do_tx(struct bu92747_port *s) } BU92747_IRDA_DBG("\n"); + if (len>0) { + s->tx_empty = 0; + } + BU92725GUW_send_data(xmit->buf+xmit->tail, len, NULL, 0); s->port.icount.tx += len; xmit->tail = (xmit->tail + len) & (UART_XMIT_SIZE - 1); - if (len>0) - s->tx_empty = 0; if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(&s->port); @@ -151,7 +148,6 @@ static void bu92747_irda_dowork(struct bu92747_port *s) static void bu92747_irda_work(struct work_struct *w) { struct bu92747_port *s = container_of(w, struct bu92747_port, work); - u32 irq_src = 0; struct circ_buf *xmit = &s->port.state->xmit; dev_dbg(s->dev, "%s\n", __func__); @@ -172,7 +168,8 @@ static void bu92747_irda_work(struct work_struct *w) static irqreturn_t bu92747_irda_irq(int irqno, void *dev_id) { struct bu92747_port *s = dev_id; - u32 irq_src = 0; + u32 irq_src = 0; + unsigned long len; dev_dbg(s->dev, "%s\n", __func__); BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__); @@ -183,19 +180,30 @@ static irqreturn_t bu92747_irda_irq(int irqno, void *dev_id) | REG_INT_AC | REG_INT_DECE | REG_INT_RDOE | REG_INT_DEX)) { BU92747_IRDA_DBG("[%s][%d]: do err\n", __FUNCTION__, __LINE__); //BU92725GUW_dump_register(); - //BU92725GUW_clr_fifo(); + BU92725GUW_clr_fifo(); BU92725GUW_reset(); + if ((BU92725GUW_SEND==irda_hw_get_mode()) + || (BU92725GUW_MULTI_SEND==irda_hw_get_mode())) { + s->tx_empty = 1; + } } if (irq_src & (REG_INT_DRX | FRM_EVT_RX_EOFRX | FRM_EVT_RX_RDE)) { - bu92747_irda_do_rx(s); + len = bu92747_irda_do_rx(s); if (!IS_FIR(s)) tty_flip_buffer_push(s->port.state->port.tty); - + else + s->cur_frame_length += len; } if ((irq_src & REG_INT_EOF) && (s->port.state->port.tty != NULL)) { tty_flip_buffer_push(s->port.state->port.tty); + if (IS_FIR(s)) { + s->last_frame_length = s->cur_frame_length; + s->cur_frame_length = 0; + atomic_set(&(s->data_ready), 1); + wake_up(&(s->data_ready_wq) ); + } } if (irq_src & (FRM_EVT_TX_TXE | FRM_EVT_TX_WRE)) { @@ -226,6 +234,10 @@ static void bu92747_irda_start_tx(struct uart_port *port) dev_dbg(s->dev, "%s\n", __func__); + //wait for start cmd + if (IS_FIR(s)) + return ; + if (s->tx_empty) bu92747_irda_do_tx(s); else @@ -256,7 +268,7 @@ static unsigned int bu92747_irda_tx_empty(struct uart_port *port) dev_dbg(s->dev, "%s\n", __func__); /* may not be truly up-to-date */ - bu92747_irda_dowork(s); + //bu92747_irda_dowork(s); return s->tx_empty; } @@ -331,6 +343,11 @@ static void bu92747_irda_shutdown(struct uart_port *port) destroy_workqueue(s->workqueue); s->workqueue = NULL; } + + atomic_set(&(s->data_ready), 0); + s->last_frame_length = 0; + s->cur_frame_length = 0; + if (s->irq) free_irq(s->irq, s); @@ -352,6 +369,8 @@ static int bu92747_irda_startup(struct uart_port *port) s->baud = 9600; s->rx_enabled = 1; + s->last_frame_length = 0; + s->cur_frame_length = 0; if (s->suspending) return 0; @@ -367,6 +386,8 @@ static int bu92747_irda_startup(struct uart_port *port) } INIT_WORK(&s->work, bu92747_irda_work); + atomic_set(&(s->data_ready), 0); + if (request_irq(s->irq, bu92747_irda_irq, IRQ_TYPE_LEVEL_LOW, "bu92747_irda", s) < 0) { dev_warn(s->dev, "cannot allocate irq %d\n", s->irq); @@ -426,7 +447,6 @@ static void bu92747_irda_set_mctrl(struct uart_port *port, unsigned int mctrl) struct bu92747_port *s = container_of(port, struct bu92747_port, port); - int rts; dev_dbg(s->dev, "%s\n", __func__); BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__); @@ -472,6 +492,57 @@ bu92747_irda_set_termios(struct uart_port *port, struct ktermios *termios, } +static int bu92747_get_frame_length(struct bu92747_port *s) +{ + unsigned long len; + wait_event_interruptible_timeout(s->data_ready_wq, + atomic_read(&(s->data_ready) ), + msecs_to_jiffies(1000) ); + if ( 0 == atomic_read(&(s->data_ready)) ) { + printk("waiting 'data_ready_wq' timed out."); + return -1; + } + + len = s->last_frame_length; + s->last_frame_length = 0; + + atomic_set(&(s->data_ready), 0); + + return len; +} + +static int bu92747_irda_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg) +{ + struct bu92747_port *s = container_of(port, + struct bu92747_port, + port); + void __user *argp = (void __user *)arg; + unsigned long len = 0; + int ret = 0; + BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__); + + switch (cmd) { + case TTYIR_GETLENGTH: + len = bu92747_get_frame_length(s); + if (len > 0) { + if (copy_to_user(argp, &len, sizeof(len))) + ret = -EFAULT; + } + else + ret = -EFAULT; + break; + + case TTYIR_STARTSEND: + bu92747_irda_dowork(s); + break; + default: + ret = -ENOIOCTLCMD; + break; + } + + return ret; +} + static struct uart_ops bu92747_irda_ops = { .tx_empty = bu92747_irda_tx_empty, .set_mctrl = bu92747_irda_set_mctrl, @@ -489,6 +560,7 @@ static struct uart_ops bu92747_irda_ops = { .request_port = bu92747_irda_request_port, .config_port = bu92747_irda_config_port, .verify_port = bu92747_irda_verify_port, + .ioctl = bu92747_irda_ioctl, }; static struct uart_driver bu92747_irda_uart_driver = { @@ -565,6 +637,8 @@ static int __devinit bu92747_irda_probe(struct platform_device *pdev) /* set shutdown mode to save power. Will be woken-up on open */ if (bu92747s[i]->pdata->irda_pwr_ctl) bu92747s[i]->pdata->irda_pwr_ctl(0); + + init_waitqueue_head(&(bu92747s[i]->data_ready_wq)); mutex_unlock(&bu92747s_lock); diff --git a/drivers/net/irda/ir_serial.h b/drivers/net/irda/ir_serial.h index c2abcac496e0..f0b3fe436bf1 100755 --- a/drivers/net/irda/ir_serial.h +++ b/drivers/net/irda/ir_serial.h @@ -3,4 +3,22 @@ #include "bu92725guw.h" +/* + * define IOCTL macro + */ +/* magic number */ +#define TTYIR_IOC_TYPE 0x56 + +/* TTYIR_STARTSEND */ +/* function: start to send a frame in FIR mode */ +/* parameter: no parameter */ +/* return: no return code */ +#define TTYIR_STARTSEND _IO(TTYIR_IOC_TYPE, 0) + +/* TTYIR_GETLENGTH */ +/* function: get the length of DATA field in the current frame */ +/* paramter: no paramter */ +/* return: the length of DATA field (unit:byte) */ +#define TTYIR_GETLENGTH _IOR(TTYIR_IOC_TYPE, 1, unsigned long) + #endif -- 2.34.1