From 59223edaa18759982db0a8aced0e77457d10c68e Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 17 Jun 1999 13:25:08 +0000 Subject: Merge with Linux 2.3.6. Sorry, this isn't tested on silicon, I don't have a MIPS box at hand. --- net/irda/ircomm/ircomm_common.c | 240 +++++++++++++++++++++------------------- net/irda/ircomm/irvtd_driver.c | 191 ++++++++++++++++++++++---------- 2 files changed, 258 insertions(+), 173 deletions(-) (limited to 'net/irda/ircomm') diff --git a/net/irda/ircomm/ircomm_common.c b/net/irda/ircomm/ircomm_common.c index bc8758e1e..5300f5f3c 100644 --- a/net/irda/ircomm/ircomm_common.c +++ b/net/irda/ircomm/ircomm_common.c @@ -8,7 +8,7 @@ * Author: Takahide Higuchi * Source: irlpt_event.c * - * Copyright (c) 1998, Takahide Higuchi, , + * Copyright (c) 1998-1999, Takahide Higuchi, , * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -41,21 +41,20 @@ #include -static char *revision_date = "Sun Apr 18 00:40:19 1999"; +static char *revision_date = "Tue May 18 03:11:39 1999"; -static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event, - struct sk_buff *skb ); - -static void ircomm_state_discoverywait( struct ircomm_cb *self, IRCOMM_EVENT event, +static void ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event, + struct sk_buff *skb ); +static void ircomm_state_discoverywait(struct ircomm_cb *self, + IRCOMM_EVENT event, + struct sk_buff *skb ); +static void ircomm_state_queryparamwait(struct ircomm_cb *self, + IRCOMM_EVENT event, struct sk_buff *skb ); - -static void ircomm_state_queryparamwait( struct ircomm_cb *self, IRCOMM_EVENT event, - struct sk_buff *skb ); - -static void ircomm_state_querylsapwait( struct ircomm_cb *self, IRCOMM_EVENT event, - struct sk_buff *skb ); - +static void ircomm_state_querylsapwait(struct ircomm_cb *self, + IRCOMM_EVENT event, + struct sk_buff *skb ); static void ircomm_state_waiti( struct ircomm_cb *self, IRCOMM_EVENT event, struct sk_buff *skb ); static void ircomm_state_waitr( struct ircomm_cb *self, IRCOMM_EVENT event, @@ -206,15 +205,17 @@ __initfunc(int ircomm_init(void)) ircomm[i]->enq_char = 0x05; ircomm[i]->ack_char = 0x06; - ircomm[i]->max_txbuff_size = COMM_DEFAULT_DATA_SIZE; /* 64 */ - ircomm[i]->maxsdusize = SAR_DISABLE; - ircomm[i]->ctrl_skb = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE); + ircomm[i]->max_header_size = COMM_MAX_HEADER_SIZE; + ircomm[i]->tx_max_sdu_size = COMM_DEFAULT_SDU_SIZE; + ircomm[i]->rx_max_sdu_size = SAR_DISABLE; + ircomm[i]->ctrl_skb = dev_alloc_skb(COMM_DEFAULT_SDU_SIZE + + COMM_MAX_HEADER_SIZE); if (ircomm[i]->ctrl_skb == NULL){ DEBUG(0,"ircomm:init_module:alloc_skb failed!\n"); return -ENOMEM; } - skb_reserve(ircomm[i]->ctrl_skb,COMM_HEADER_SIZE); + skb_reserve(ircomm[i]->ctrl_skb,COMM_MAX_HEADER_SIZE); } @@ -226,7 +227,6 @@ __initfunc(int ircomm_init(void)) create_proc_entry("ircomm", 0, proc_irda)->get_info = ircomm_proc_read; #endif /* CONFIG_PROC_FS */ - discovering_instance = NULL; return 0; } @@ -275,51 +275,55 @@ void ircomm_cleanup(void) static int ircomm_accept_data_indication(void *instance, void *sap, struct sk_buff *skb) { - - struct ircomm_cb *self = (struct ircomm_cb *)instance; + struct ircomm_cb *self = (struct ircomm_cb *) instance; - ASSERT( self != NULL, return -1;); - ASSERT( self->magic == IRCOMM_MAGIC, return -1;); - ASSERT( skb != NULL, return -1;); + ASSERT(self != NULL, return -1;); + ASSERT(self->magic == IRCOMM_MAGIC, return -1;); + ASSERT(skb != NULL, return -1;); DEBUG(4,__FUNCTION__"():\n"); - ircomm_do_event( self, TTP_DATA_INDICATION, skb); + ircomm_do_event(self, TTP_DATA_INDICATION, skb); self->rx_packets++; return 0; } static void ircomm_accept_connect_confirm(void *instance, void *sap, - struct qos_info *qos, - __u32 maxsdusize, struct sk_buff *skb) + struct qos_info *qos, + __u32 max_sdu_size, + __u8 max_header_size, + struct sk_buff *skb) { + struct ircomm_cb *self = (struct ircomm_cb *) instance; - struct ircomm_cb *self = (struct ircomm_cb *)instance; - - ASSERT( self != NULL, return;); - ASSERT( self->magic == IRCOMM_MAGIC, return;); - ASSERT( skb != NULL, return;); - ASSERT( qos != NULL, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == IRCOMM_MAGIC, return;); + ASSERT(skb != NULL, return;); + ASSERT(qos != NULL, return;); DEBUG(0,__FUNCTION__"(): got connected!\n"); - if(maxsdusize == SAR_DISABLE) - self->max_txbuff_size = qos->data_size.value; + if (max_sdu_size == SAR_DISABLE) + self->tx_max_sdu_size =(qos->data_size.value - max_header_size + - COMM_HEADER_SIZE); else { - ASSERT(maxsdusize >= COMM_DEFAULT_DATA_SIZE, return;); - self->max_txbuff_size = maxsdusize; /* use fragmentation */ + ASSERT(max_sdu_size >= COMM_DEFAULT_SDU_SIZE, return;); + /* use fragmentation */ + self->tx_max_sdu_size = max_sdu_size - COMM_HEADER_SIZE; } self->qos = qos; - self->null_modem_mode = 0; /* disable null modem emulation */ + self->max_header_size = max_header_size + COMM_HEADER_SIZE; + self->null_modem_mode = 0; /* disable null modem emulation */ - ircomm_do_event( self, TTP_CONNECT_CONFIRM, skb); + ircomm_do_event(self, TTP_CONNECT_CONFIRM, skb); } static void ircomm_accept_connect_indication(void *instance, void *sap, - struct qos_info *qos, - __u32 maxsdusize, - struct sk_buff *skb ) + struct qos_info *qos, + __u32 max_sdu_size, + __u8 max_header_size, + struct sk_buff *skb) { struct ircomm_cb *self = (struct ircomm_cb *)instance; @@ -330,12 +334,15 @@ static void ircomm_accept_connect_indication(void *instance, void *sap, DEBUG(0,__FUNCTION__"()\n"); - if(maxsdusize == SAR_DISABLE) - self->max_txbuff_size = qos->data_size.value; + if (max_sdu_size == SAR_DISABLE) + self->tx_max_sdu_size =(qos->data_size.value - max_header_size + - COMM_HEADER_SIZE); else - self->max_txbuff_size = maxsdusize; + self->tx_max_sdu_size = max_sdu_size - COMM_HEADER_SIZE; self->qos = qos; + self->max_header_size = max_header_size + COMM_HEADER_SIZE; + ircomm_do_event( self, TTP_CONNECT_INDICATION, skb); /* stop connecting */ @@ -556,7 +563,7 @@ static void issue_connect_request(struct ircomm_cb *self, irttp_connect_request(self->tsap, self->dlsap, self->saddr, self->daddr, - NULL, self->maxsdusize, userdata); + NULL, self->rx_max_sdu_size, userdata); break; default: @@ -588,9 +595,10 @@ static void connect_indication(struct ircomm_cb *self, struct qos_info *qos, /* if( !ircomm_parse_controlchannel( self, data)) */ /* self->servicetype = DEFAULT; TODOD:fix this! TH */ - if(self->notify.connect_indication) + if (self->notify.connect_indication) self->notify.connect_indication(self->notify.instance, self, - qos, 0, skb); + qos, self->tx_max_sdu_size, + self->max_header_size, skb); } #if 0 @@ -602,28 +610,27 @@ static void connect_indication_three_wire_raw(void) #endif -static void connect_confirmation(struct ircomm_cb *self, struct sk_buff *skb) +static void connect_confirm(struct ircomm_cb *self, struct sk_buff *skb) { DEBUG(4 ,__FUNCTION__"()\n"); /* give a connect_confirm to the client */ if( self->notify.connect_confirm ) self->notify.connect_confirm(self->notify.instance, - self, NULL, SAR_DISABLE, skb); + self, NULL, self->tx_max_sdu_size, + self->max_header_size, skb); } static void issue_connect_response(struct ircomm_cb *self, struct sk_buff *skb) { - DEBUG(0,__FUNCTION__"()\n"); if( self->servicetype == THREE_WIRE_RAW){ DEBUG(0,__FUNCTION__"():THREE_WIRE_RAW is not implemented yet\n"); /* irlmp_connect_rsp(); */ - } else { - irttp_connect_response(self->tsap, self->maxsdusize, skb); - } + } else + irttp_connect_response(self->tsap, self->rx_max_sdu_size, skb); } static void issue_disconnect_request(struct ircomm_cb *self, @@ -642,30 +649,29 @@ static void issue_data_request(struct ircomm_cb *self, { int err; - if(self->servicetype == THREE_WIRE_RAW){ + if (self->servicetype == THREE_WIRE_RAW){ /* irlmp_data_request(self->lmhandle,userdata); */ DEBUG(0,__FUNCTION__"():not implemented!"); return; } DEBUG(4,__FUNCTION__"():sending frame\n"); - err = irttp_data_request(self->tsap , userdata ); - if(err){ + err = irttp_data_request(self->tsap, userdata); + if (err){ printk(KERN_ERR __FUNCTION__":ttp_data_request failed\n"); - if(userdata) + if (userdata) dev_kfree_skb( userdata); } self->tx_packets++; } static void issue_control_request(struct ircomm_cb *self, - struct sk_buff *userdata ) + struct sk_buff *userdata) { int err; DEBUG(4,__FUNCTION__"()\n"); - if(self->servicetype == THREE_WIRE_RAW) - { + if (self->servicetype == THREE_WIRE_RAW) { DEBUG(0,__FUNCTION__"():THREE_WIRE_RAW is not implemented\n"); } @@ -676,7 +682,7 @@ static void issue_control_request(struct ircomm_cb *self, { printk( __FUNCTION__"():ttp_data_request failed\n"); if(userdata) - dev_kfree_skb( userdata); + dev_kfree_skb(userdata); } else self->tx_controls++; @@ -701,7 +707,7 @@ static void process_data(struct ircomm_cb *self, struct sk_buff *skb ) /* ircomm_parse_control(self, skb, CONTROL_CHANNEL); */ - if(self->notify.data_indication && skb->len) + if (self->notify.data_indication && skb->len) self->notify.data_indication(self->notify.instance, self, skb); } @@ -728,7 +734,7 @@ static void ircomm_do_event( struct ircomm_cb *self, IRCOMM_EVENT event, DEBUG( 4, __FUNCTION__": STATE = %s, EVENT = %s\n", ircommstate[self->state], ircommevent[event]); - (*state[ self->state ]) ( self, event, skb); + (*state[self->state])(self, event, skb); } static void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state) @@ -747,7 +753,7 @@ static void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state) static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event, struct sk_buff *skb ) { - switch(event){ + switch (event){ case IRCOMM_CONNECT_REQUEST: /* ircomm_next_state(self, COMM_WAITI); */ @@ -779,7 +785,8 @@ static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event, /* * ircomm_state_discoverywait */ -static void ircomm_state_discoverywait(struct ircomm_cb *self, IRCOMM_EVENT event, +static void ircomm_state_discoverywait(struct ircomm_cb *self, + IRCOMM_EVENT event, struct sk_buff *skb ) { switch(event){ @@ -817,11 +824,11 @@ static void ircomm_state_discoverywait(struct ircomm_cb *self, IRCOMM_EVENT even * ircomm_state_queryparamwait */ -static void ircomm_state_queryparamwait(struct ircomm_cb *self, IRCOMM_EVENT event, - struct sk_buff *skb ) +static void ircomm_state_queryparamwait(struct ircomm_cb *self, + IRCOMM_EVENT event, + struct sk_buff *skb) { - switch(event){ - + switch (event) { case TTP_CONNECT_INDICATION: ircomm_next_state(self, COMM_WAITR); @@ -855,10 +862,11 @@ static void ircomm_state_queryparamwait(struct ircomm_cb *self, IRCOMM_EVENT eve * ircomm_state_querylsapwait */ -static void ircomm_state_querylsapwait(struct ircomm_cb *self, IRCOMM_EVENT event, +static void ircomm_state_querylsapwait(struct ircomm_cb *self, + IRCOMM_EVENT event, struct sk_buff *skb ) { - switch(event){ + switch (event) { case TTP_CONNECT_INDICATION: @@ -898,10 +906,10 @@ static void ircomm_state_querylsapwait(struct ircomm_cb *self, IRCOMM_EVENT even static void ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event, struct sk_buff *skb ) { - switch(event){ + switch (event) { case TTP_CONNECT_CONFIRM: ircomm_next_state(self, COMM_CONN); - connect_confirmation( self, skb ); + connect_confirm(self, skb ); break; case TTP_DISCONNECT_INDICATION: ircomm_next_state(self, COMM_IDLE); @@ -921,21 +929,18 @@ static void ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event, } } - - /* * ircomm_state_waitr */ static void ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event, - struct sk_buff *skb ) + struct sk_buff *skb ) { - - switch(event){ + switch (event) { case IRCOMM_CONNECT_RESPONSE: /* issue_connect_response */ - if(self->servicetype==THREE_WIRE_RAW){ + if (self->servicetype==THREE_WIRE_RAW) { DEBUG(0,__FUNCTION__"():3WIRE_RAW is not implemented\n"); /* irlmp_connect_response(Vpeersap, * ACCEPT,null); @@ -987,7 +992,7 @@ static void ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event, static void ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, struct sk_buff *skb ) { - switch(event){ + switch (event) { case TTP_DATA_INDICATION: process_data(self, skb); break; @@ -1033,8 +1038,6 @@ static void ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, } } - - /* * ---------------------------------------------------------------------- * IrCOMM service interfaces and supporting functions @@ -1042,12 +1045,12 @@ static void ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, * ---------------------------------------------------------------------- */ -/* - * start_discovering() +/* + * Function start_discovering (self) + * + * Start discovering and enter DISCOVERY_WAIT state * - * start discovering and enter DISCOVERY_WAIT state */ - static void start_discovering(struct ircomm_cb *self) { __u16 hints; @@ -1058,7 +1061,7 @@ static void start_discovering(struct ircomm_cb *self) hints = irlmp_service_to_hint(S_COMM); - DEBUG(0,__FUNCTION__"():start discovering..\n"); + DEBUG(1,__FUNCTION__"():start discovering..\n"); switch (ircomm_cs) { case 0: MOD_INC_USE_COUNT; @@ -1092,19 +1095,26 @@ static void start_discovering(struct ircomm_cb *self) /* * queryias_done(self) * - * called when discovery process got wrong results, completed, or terminated. + * */ +/* + * Function queryias_done (self) + * + * Called when discovery process got wrong results, completed, or + * terminated. + * + */ static void queryias_done(struct ircomm_cb *self) { DEBUG(0, __FUNCTION__"():\n"); - if(self->queryias_lock){ + if (self->queryias_lock){ self->queryias_lock = 0; discovering_instance = NULL; MOD_DEC_USE_COUNT; irlmp_unregister_client(self->ckey); } - if(ircomm_cs != 1) + if (ircomm_cs != 1) irlmp_unregister_service(self->skey); return; } @@ -1120,7 +1130,6 @@ static void query_parameters(struct ircomm_cb *self) ircomm_getvalue_confirm, self ); } - static void query_lsapsel(struct ircomm_cb * self) { DEBUG(0, __FUNCTION__"():querying IAS: Lsapsel...\n"); @@ -1135,13 +1144,13 @@ static void query_lsapsel(struct ircomm_cb * self) } } -/* - * ircomm_connect_request() - * Impl. of this function is differ from one of the reference. - * This functin does discovery as well as sending connect request +/* + * Function ircomm_connect_request (self, servicetype) + * + * Impl. of this function is differ from one of the reference. This + * function does discovery as well as sending connect request + * */ - - void ircomm_connect_request(struct ircomm_cb *self, __u8 servicetype) { /* @@ -1153,17 +1162,17 @@ void ircomm_connect_request(struct ircomm_cb *self, __u8 servicetype) ASSERT( self->magic == IRCOMM_MAGIC, return;); - DEBUG(0, __FUNCTION__"():sending connect_request...\n"); + DEBUG(1, __FUNCTION__"():sending connect_request...\n"); self->servicetype= servicetype; /* ircomm_control_request(self, SERVICETYPE); */ /*servictype*/ - self->maxsdusize = SAR_DISABLE; - ircomm_do_event( self, IRCOMM_CONNECT_REQUEST, NULL); + self->rx_max_sdu_size = SAR_DISABLE; + ircomm_do_event(self, IRCOMM_CONNECT_REQUEST, NULL); } void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata, - __u32 maxsdusize) + __u32 max_sdu_size) { ASSERT( self != NULL, return;); @@ -1177,20 +1186,20 @@ void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata, * and send it with connect_response */ - if(!userdata){ + if (!userdata){ /* FIXME: check for errors and initialize? DB */ - userdata = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE); - ASSERT(userdata != NULL, return;); + userdata = dev_alloc_skb(COMM_DEFAULT_SDU_SIZE + COMM_MAX_HEADER_SIZE); + if (userdata == NULL) + return; - skb_reserve(userdata,COMM_HEADER_SIZE); + skb_reserve(userdata,COMM_MAX_HEADER_SIZE); } /* enable null-modem emulation (i.e. server mode )*/ self->null_modem_mode = 1; - self->maxsdusize = maxsdusize; - if(maxsdusize != SAR_DISABLE) - self->max_txbuff_size = maxsdusize; + self->rx_max_sdu_size = max_sdu_size; + ircomm_do_event(self, IRCOMM_CONNECT_RESPONSE, userdata); } @@ -1303,10 +1312,10 @@ static void ircomm_tx_controlchannel(struct ircomm_cb *self ) ircomm_do_event(self, IRCOMM_CONTROL_REQUEST, skb); self->control_ch_pending = 0; - skb = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE); + skb = dev_alloc_skb(COMM_DEFAULT_SDU_SIZE + COMM_MAX_HEADER_SIZE); ASSERT(skb != NULL, return ;); - skb_reserve(skb,COMM_HEADER_SIZE); + skb_reserve(skb,COMM_MAX_HEADER_SIZE); self->ctrl_skb = skb; } @@ -1341,14 +1350,13 @@ static void append_tuple(struct ircomm_cb *self, __u8 instruction, __u8 pl , self->control_ch_pending = 1; } - - /* - * ircomm_control_request(); - * this function is exported as a request to send some control-channel tuples - * to peer device + * Function ircomm_control_request (self, instruction) + * + * This function is exported as a request to send some control-channel + * tuples * to peer device + * */ - void ircomm_control_request(struct ircomm_cb *self, __u8 instruction) { diff --git a/net/irda/ircomm/irvtd_driver.c b/net/irda/ircomm/irvtd_driver.c index 2df2fdd60..7b1ddf3cb 100644 --- a/net/irda/ircomm/irvtd_driver.c +++ b/net/irda/ircomm/irvtd_driver.c @@ -8,7 +8,7 @@ * Source: serial.c by Linus Torvalds * isdn_tty.c by Fritz Elfert * - * Copyright (c) 1998, Takahide Higuchi, , + * Copyright (c) 1998-1999, Takahide Higuchi, , * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -51,7 +51,7 @@ struct termios *irvtd_termios_locked[COMM_MAX_TTY]; static int irvtd_refcount; struct irvtd_cb **irvtd = NULL; -static char *revision_date = "Sun Apr 18 17:31:53 1999"; +static char *revision_date = "Wed May 26 00:49:11 1999"; /* @@ -83,8 +83,10 @@ static void irvtd_break(struct tty_struct *tty, int break_state); static void irvtd_send_xchar(struct tty_struct *tty, char ch); static void irvtd_wait_until_sent(struct tty_struct *tty, int timeout); -static void irvtd_start_timer( struct irvtd_cb *driver); -static void irvtd_timer_expired(unsigned long data); +static void irvtd_start_tx_timer( struct irvtd_cb *driver, int timeout); +static void irvtd_tx_timer_expired(unsigned long data); +static void irvtd_start_rx_timer( struct irvtd_cb *driver, int timeout); +static void irvtd_rx_timer_expired(unsigned long data); static int line_info(char *buf, struct irvtd_cb *driver); static int irvtd_read_proc(char *buf, char **start, off_t offset, int len, @@ -118,7 +120,7 @@ static void irvtd_write_to_tty( struct irvtd_cb *driver) if(driver->rx_disable) return; - skb = skb_dequeue(&driver->rxbuff); + skb = skb_dequeue(&driver->rxbuff); if(skb == NULL) return; /* there's nothing */ @@ -211,8 +213,13 @@ static void irvtd_write_to_tty( struct irvtd_cb *driver) if(skb_queue_len(&driver->rxbuff)< IRVTD_RX_QUEUE_LOW && driver->ttp_stoprx){ - irttp_flow_request(driver->comm->tsap, FLOW_START); + DEBUG(1, __FUNCTION__"():FLOW_START\n"); + /* + * next 2 lines must follow this order since irttp_flow_request() + * will run its rx queue + */ driver->ttp_stoprx = 0; + irttp_flow_request(driver->comm->tsap, FLOW_START); } if(skb_queue_empty(&driver->rxbuff) && driver->disconnect_pend){ @@ -236,10 +243,14 @@ static int irvtd_receive_data(void *instance, void *sap, struct sk_buff *skb) skb_queue_tail( &driver->rxbuff, skb ); if(skb_queue_len(&driver->rxbuff) > IRVTD_RX_QUEUE_HIGH){ + DEBUG(1, __FUNCTION__"():FLOW_STOP\n"); irttp_flow_request(driver->comm->tsap, FLOW_STOP); driver->ttp_stoprx = 1; } irvtd_write_to_tty(driver); + + if(!skb_queue_empty(&driver->rxbuff)) + irvtd_start_rx_timer(driver,0); return 0; } @@ -255,22 +266,36 @@ static int irvtd_receive_data(void *instance, void *sap, struct sk_buff *skb) */ -static void irvtd_start_timer( struct irvtd_cb *driver) +static void irvtd_start_tx_timer( struct irvtd_cb *driver, int timeout) +{ + ASSERT( driver != NULL, return;); + ASSERT( driver->magic == IRVTD_MAGIC, return;); + + del_timer( &driver->tx_timer); + + driver->tx_timer.data = (unsigned long) driver; + driver->tx_timer.function = &irvtd_tx_timer_expired; + driver->tx_timer.expires = jiffies + timeout; + + add_timer( &driver->tx_timer); +} + +static void irvtd_start_rx_timer( struct irvtd_cb *driver, int timeout) { ASSERT( driver != NULL, return;); ASSERT( driver->magic == IRVTD_MAGIC, return;); - del_timer( &driver->timer); + del_timer( &driver->rx_timer); - driver->timer.data = (unsigned long) driver; - driver->timer.function = &irvtd_timer_expired; - driver->timer.expires = jiffies + (HZ / 5); /* 200msec */ + driver->rx_timer.data = (unsigned long) driver; + driver->rx_timer.function = &irvtd_rx_timer_expired; + driver->rx_timer.expires = jiffies + timeout; - add_timer( &driver->timer); + add_timer( &driver->rx_timer); } -static void irvtd_timer_expired(unsigned long data) +static void irvtd_tx_timer_expired(unsigned long data) { struct irvtd_cb *driver = (struct irvtd_cb *)data; @@ -279,11 +304,26 @@ static void irvtd_timer_expired(unsigned long data) DEBUG(4, __FUNCTION__"()\n"); irvtd_send_data_request(driver); +} - irvtd_write_to_tty(driver); +static void irvtd_rx_timer_expired(unsigned long data) +{ + struct irvtd_cb *driver = (struct irvtd_cb *)data; + + ASSERT(driver != NULL,return;); + ASSERT(driver->magic == IRVTD_MAGIC,return;); + DEBUG(4, __FUNCTION__"()\n"); - /* start our timer again and again */ - irvtd_start_timer(driver); + while(TTY_FLIPBUF_SIZE - driver->tty->flip.count + && !skb_queue_empty(&driver->rxbuff)) + irvtd_write_to_tty(driver); + + DEBUG(1, __FUNCTION__"(): room in flip_buffer = %d\n", + TTY_FLIPBUF_SIZE - driver->tty->flip.count); + + if(!skb_queue_empty(&driver->rxbuff)) + /* handle it later */ + irvtd_start_rx_timer(driver, 1); } @@ -310,21 +350,23 @@ static void irvtd_send_data_request(struct irvtd_cb *driver) } #endif - DEBUG(1, __FUNCTION__"():sending %d octets\n",(int)skb->len ); + DEBUG(1, __FUNCTION__"():len = %d, room = %d\n",(int)skb->len, + skb_tailroom(skb)); driver->icount.tx += skb->len; err = ircomm_data_request(driver->comm, driver->txbuff); if (err){ ASSERT(err == 0,;); - DEBUG(0,"%d chars are lost\n",(int)skb->len); + DEBUG(1,"%d chars are lost\n",(int)skb->len); skb_trim(skb, 0); } /* allocate a new frame */ - skb = driver->txbuff = dev_alloc_skb(driver->comm->max_txbuff_size); + skb = driver->txbuff + = dev_alloc_skb(driver->tx_max_sdu_size + driver->max_header_size); if (skb == NULL){ printk(__FUNCTION__"():alloc_skb failed!\n"); } else { - skb_reserve(skb, COMM_HEADER_SIZE); + skb_reserve(skb, driver->max_header_size); } wake_up_interruptible(&driver->tty->write_wait); @@ -341,20 +383,23 @@ static void irvtd_send_data_request(struct irvtd_cb *driver) *********************************************************************** */ - /* * Function irvtd_connect_confirm (instance, sap, qos, max_sdu_size, skb) * - * ircomm_connect_request which we have send have succeed! + * ircomm_connect_request which we have send, has succeeded! * */ void irvtd_connect_confirm(void *instance, void *sap, struct qos_info *qos, - __u32 max_sdu_size, struct sk_buff *skb) + __u32 max_sdu_size, __u8 max_header_size, + struct sk_buff *skb) { struct irvtd_cb *driver = (struct irvtd_cb *)instance; ASSERT(driver != NULL, return;); ASSERT(driver->magic == IRVTD_MAGIC, return;); + + driver->tx_max_sdu_size = max_sdu_size; + driver->max_header_size = max_header_size; /* * set default value */ @@ -364,7 +409,7 @@ void irvtd_connect_confirm(void *instance, void *sap, struct qos_info *qos, /* * sending initial control parameters here */ - if(driver->comm->servicetype == THREE_WIRE_RAW) + if (driver->comm->servicetype == THREE_WIRE_RAW) return; /* do nothing */ driver->comm->dte |= (MCR_DTR | MCR_RTS | DELTA_DTR | DELTA_RTS); @@ -376,7 +421,7 @@ void irvtd_connect_confirm(void *instance, void *sap, struct qos_info *qos, ircomm_control_request(driver->comm, XON_XOFF_CHAR); /* ircomm_control_request(driver->comm, ENQ_ACK_CHAR); */ - switch(driver->comm->servicetype){ + switch (driver->comm->servicetype) { case CENTRONICS: break; @@ -397,17 +442,20 @@ void irvtd_connect_confirm(void *instance, void *sap, struct qos_info *qos, * */ void irvtd_connect_indication(void *instance, void *sap, struct qos_info *qos, - __u32 max_sdu_size, struct sk_buff *skb) + __u32 max_sdu_size, __u8 max_header_size, + struct sk_buff *skb) { - struct irvtd_cb *driver = (struct irvtd_cb *)instance; struct ircomm_cb *comm = (struct ircomm_cb *)sap; + ASSERT(driver != NULL, return;); ASSERT(driver->magic == IRVTD_MAGIC, return;); ASSERT(comm != NULL, return;); ASSERT(comm->magic == IRCOMM_MAGIC, return;); - DEBUG(4,"irvtd_connect_indication:sending connect_response...\n"); + driver->tx_max_sdu_size = max_sdu_size; + driver->max_header_size = max_header_size; + DEBUG(4, __FUNCTION__ "():sending connect_response...\n"); ircomm_connect_response(comm, NULL, SAR_DISABLE ); @@ -416,7 +464,7 @@ void irvtd_connect_indication(void *instance, void *sap, struct qos_info *qos, /* * send initial control parameters */ - if(driver->comm->servicetype == THREE_WIRE_RAW) + if (driver->comm->servicetype == THREE_WIRE_RAW) return; /* do nothing */ driver->comm->dte |= (MCR_DTR | MCR_RTS | DELTA_DTR | DELTA_RTS); @@ -426,6 +474,7 @@ void irvtd_connect_indication(void *instance, void *sap, struct qos_info *qos, ircomm_control_request(driver->comm, DTELINE_STATE); break; default: + DEBUG(0, __FUNCTION__ "(), not implemented!\n"); } @@ -479,11 +528,12 @@ void irvtd_control_indication(void *instance, void *sap, IRCOMM_CMD cmd) if(cmd == TX_READY){ driver->ttp_stoptx = 0; driver->tty->hw_stopped = driver->cts_stoptx; - irvtd_start_timer( driver); if(driver->cts_stoptx) return; + /* push tx queue so that client can send at least 1 octet */ + irvtd_send_data_request(driver); /* * driver->tty->write_wait will keep asleep if * our txbuff is full. @@ -498,7 +548,7 @@ void irvtd_control_indication(void *instance, void *sap, IRCOMM_CMD cmd) if(cmd == TX_BUSY){ driver->ttp_stoptx = driver->tty->hw_stopped = 1; - del_timer( &driver->timer); + del_timer( &driver->tx_timer); return; } @@ -576,6 +626,7 @@ void irvtd_control_indication(void *instance, void *sap, IRCOMM_CMD cmd) case DATA_RATE: case XON_XOFF_CHAR: case DTELINE_STATE: + case ENQ_ACK_CHAR: /* got this from win95 */ /* (maybe) nothing to do */ break; default: @@ -607,7 +658,7 @@ static int irvtd_block_til_ready(struct tty_struct *tty, struct file * filp, struct irvtd_cb *driver) { - struct wait_queue wait = { current, NULL }; + DECLARE_WAITQUEUE(wait,current); int retval = 0; int do_clocal = 0; @@ -678,7 +729,7 @@ static int irvtd_block_til_ready(struct tty_struct *tty, struct file * filp, driver->blocked_open--; - DEBUG(0, __FUNCTION__"():after blocking\n"); + DEBUG(1, __FUNCTION__"():after blocking\n"); if (retval) return retval; @@ -765,7 +816,7 @@ static int irvtd_startup(struct irvtd_cb *driver) struct notify_t irvtd_notify; /* FIXME: it should not be hard coded */ - __u8 oct_seq[6] = { 0,1,4,1,1,1 }; + __u8 oct_seq[6] = { 0,1,6,1,1,1 }; DEBUG(4,__FUNCTION__"()\n" ); if(driver->flags & ASYNC_INITIALIZED) @@ -776,12 +827,12 @@ static int irvtd_startup(struct irvtd_cb *driver) */ skb_queue_head_init(&driver->rxbuff); - driver->txbuff = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE); + driver->txbuff = dev_alloc_skb(COMM_DEFAULT_SDU_SIZE + COMM_MAX_HEADER_SIZE); if (!driver->txbuff){ - DEBUG(0,__FUNCTION__"():alloc_skb failed!\n"); + DEBUG(0,__FUNCTION__"(), alloc_skb failed!\n"); return -ENOMEM; } - skb_reserve(driver->txbuff, COMM_HEADER_SIZE); + skb_reserve(driver->txbuff, COMM_MAX_HEADER_SIZE); irda_notify_init(&irvtd_notify); irvtd_notify.data_indication = irvtd_receive_data; @@ -793,9 +844,8 @@ static int irvtd_startup(struct irvtd_cb *driver) irvtd_notify.instance = driver; driver->comm = ircomm_open_instance(irvtd_notify); - if(!driver->comm){ + if (!driver->comm) return -ENODEV; - } /* @@ -811,22 +861,20 @@ static int irvtd_startup(struct irvtd_cb *driver) driver->flags |= ASYNC_INITIALIZED; - /* - * discover a peer device - * TODO: other servicetype(i.e. 3wire,3wireraw) support - */ - ircomm_connect_request(driver->comm, NINE_WIRE); - - /* - * TODO:we have to initialize control-channel here! - * i.e.set something into RTS,CTS and so on.... - */ - if (driver->tty) clear_bit(TTY_IO_ERROR, &driver->tty->flags); change_speed(driver); - irvtd_start_timer( driver); + + /* + * discover a peer device + */ + if(driver->tty->termios->c_cflag & CRTSCTS) + ircomm_connect_request(driver->comm, NINE_WIRE); + else + ircomm_connect_request(driver->comm, THREE_WIRE); + + /* irvtd_start_timer( driver); */ driver->rx_disable = 0; driver->tx_disable = 1; @@ -989,7 +1037,8 @@ static void irvtd_shutdown(struct irvtd_cb * driver) if (driver->tty) set_bit(TTY_IO_ERROR, &driver->tty->flags); - del_timer( &driver->timer); + del_timer( &driver->tx_timer); + del_timer( &driver->rx_timer); irias_delete_object("IrDA:IrCOMM"); @@ -1144,13 +1193,21 @@ int irvtd_write(struct tty_struct * tty, int from_user, DEBUG(4, __FUNCTION__"()\n"); save_flags(flags); - while(1){ + while(count > 0){ cli(); skb = driver->txbuff; ASSERT(skb != NULL, break;); c = MIN(count, (skb_tailroom(skb))); if (c <= 0) - break; + { + if(!driver->ttp_stoptx) + { + irvtd_send_data_request(driver); + continue; + } + else + break; + } /* write to the frame */ @@ -1164,9 +1221,9 @@ int irvtd_write(struct tty_struct * tty, int from_user, wrote += c; count -= c; buf += c; - irvtd_send_data_request(driver); } restore_flags(flags); + irvtd_send_data_request(driver); return (wrote); } @@ -1199,19 +1256,27 @@ void irvtd_put_char(struct tty_struct *tty, unsigned char ch) DEBUG(4, __FUNCTION__"()\n"); + again: save_flags(flags);cli(); skb = driver->txbuff; ASSERT(skb != NULL,return;); + if(!skb_tailroom(skb)) + { + restore_flags(flags); + irvtd_send_data_request(driver); + goto again; + } ASSERT(skb_tailroom(skb) > 0, return;); - DEBUG(4, "irvtd_put_char(0x%02x) skb_len(%d) MAX(%d):\n", + DEBUG(4, "irvtd_put_char(0x%02x) skb_len(%d) room(%d):\n", (int)ch ,(int)skb->len, - driver->comm->max_txbuff_size - COMM_HEADER_SIZE); + skb_tailroom(skb)); /* append a character */ frame = skb_put(skb,1); frame[0] = ch; restore_flags(flags); + irvtd_start_tx_timer(driver,20); return; } @@ -1635,6 +1700,7 @@ void irvtd_throttle(struct tty_struct *tty){ driver->comm->dte = driver->mcr; ircomm_control_request(driver->comm, DTELINE_STATE ); + DEBUG(1, __FUNCTION__"():FLOW_STOP\n"); irttp_flow_request(driver->comm->tsap, FLOW_STOP); } @@ -1649,6 +1715,7 @@ void irvtd_unthrottle(struct tty_struct *tty){ driver->comm->dte = driver->mcr; ircomm_control_request(driver->comm, DTELINE_STATE ); + DEBUG(1, __FUNCTION__"():FLOW_START\n"); irttp_flow_request(driver->comm->tsap, FLOW_START); } @@ -1859,6 +1926,12 @@ static int line_info(char *buf, struct irvtd_cb *driver) if (driver->msr & MSR_RI) ret += sprintf(buf+ret, "|RI"); + ret += sprintf(buf+ret, "\n"); + ret += sprintf(buf+ret, "rx queue:%d", + skb_queue_len( &driver->rxbuff)); + ret += sprintf(buf+ret, "ttp_stoprx:%s", + driver->ttp_stoprx?"TRUE":"FALSE"); + exit: ret += sprintf(buf+ret, "\n"); return ret; @@ -1930,6 +2003,10 @@ __initfunc(int irvtd_init(void)) irvtd[i]->line = i; irvtd[i]->closing_wait = 10*HZ ; irvtd[i]->close_delay = 5*HZ/10 ; + init_waitqueue_head(&irvtd[i]->open_wait); + init_waitqueue_head(&irvtd[i]->close_wait); + init_waitqueue_head(&irvtd[i]->tx_wait); + init_waitqueue_head(&irvtd[i]->delta_msr_wait); } /* -- cgit v1.2.3