patch-2.2.15 linux/net/irda/irttp.c
Next file: linux/net/irda/parameters.c
Previous file: linux/net/irda/irsysctl.c
Back to the patch index
Back to the overall index
- Lines: 1172
- Date:
Fri Apr 21 12:47:16 2000
- Orig file:
v2.2.14/net/irda/irttp.c
- Orig date:
Sat Aug 14 02:26:54 1999
diff -u --new-file --recursive --exclude-from ../../exclude v2.2.14/net/irda/irttp.c linux/net/irda/irttp.c
@@ -3,13 +3,13 @@
* Filename: irttp.c
* Version: 1.2
* Description: Tiny Transport Protocol (TTP) implementation
- * Status: Experimental.
+ * Status: Stable
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Aug 31 20:14:31 1997
- * Modified at: Mon May 31 10:29:56 1999
+ * Modified at: Sun Jan 30 14:30:32 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
- * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
+ * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
@@ -32,7 +32,9 @@
#include <net/irda/irda.h>
#include <net/irda/irmod.h>
+#include <net/irda/irlap.h>
#include <net/irda/irlmp.h>
+#include <net/irda/parameters.h>
#include <net/irda/irttp.h>
static struct irttp_cb *irttp = NULL;
@@ -58,6 +60,16 @@
static void irttp_fragment_skb(struct tsap_cb *self, struct sk_buff *skb);
static void irttp_start_todo_timer(struct tsap_cb *self, int timeout);
static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self);
+static int irttp_param_max_sdu_size(void *instance, irda_param_t *param,
+ int get);
+
+/* Information for parsing parameters in IrTTP */
+static pi_minor_info_t pi_minor_call_table[] = {
+ { NULL, 0 }, /* 0x00 */
+ { irttp_param_max_sdu_size, PV_INTEGER | PV_BIG_ENDIAN } /* 0x01 */
+};
+static pi_major_info_t pi_major_call_table[] = {{ pi_minor_call_table, 2 }};
+static pi_param_info_t param_info = { pi_major_call_table, 1, 0x0f, 4 };
/*
* Function irttp_init (void)
@@ -65,7 +77,7 @@
* Initialize the IrTTP layer. Called by module initialization code
*
*/
-__initfunc(int irttp_init(void))
+int __init irttp_init(void)
{
/* Initialize the irttp structure. */
if (irttp == NULL) {
@@ -79,7 +91,7 @@
irttp->tsaps = hashbin_new(HB_LOCAL);
if (!irttp->tsaps) {
- printk(KERN_WARNING "IrDA: Can't allocate IrTTP hashbin!\n");
+ ERROR(__FUNCTION__ "(), can't allocate IrTTP hashbin!\n");
return -ENOMEM;
}
@@ -118,22 +130,22 @@
*
* Create TSAP connection endpoint,
*/
-struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit,
- struct notify_t *notify)
+struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify)
{
- struct notify_t ttp_notify;
struct tsap_cb *self;
struct lsap_cb *lsap;
+ notify_t ttp_notify;
ASSERT(irttp != NULL, return NULL;);
ASSERT(irttp->magic == TTP_MAGIC, return NULL;);
self = kmalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
if (self == NULL) {
- DEBUG(0, __FUNCTION__ "(), unable to kmalloc!\n");
+ IRDA_DEBUG(0, __FUNCTION__ "(), unable to kmalloc!\n");
return NULL;
}
memset(self, 0, sizeof(struct tsap_cb));
+ spin_lock_init(&self->lock);
init_timer(&self->todo_timer);
@@ -156,9 +168,9 @@
/*
* Create LSAP at IrLMP layer
*/
- lsap = irlmp_open_lsap(stsap_sel, &ttp_notify);
+ lsap = irlmp_open_lsap(stsap_sel, &ttp_notify, 0);
if (lsap == NULL) {
- printk(KERN_ERR "IrTTP, Unable to get LSAP!!\n");
+ WARNING(__FUNCTION__ "(), unable to allocate LSAP!!\n");
return NULL;
}
@@ -168,12 +180,12 @@
* the stsap_sel we have might not be valid anymore
*/
self->stsap_sel = lsap->slsap_sel;
- DEBUG(4, __FUNCTION__ "(), stsap_sel=%02x\n", self->stsap_sel);
+ IRDA_DEBUG(4, __FUNCTION__ "(), stsap_sel=%02x\n", self->stsap_sel);
self->notify = *notify;
self->lsap = lsap;
- hashbin_insert(irttp->tsaps, (QUEUE *) self, (int) self, NULL);
+ hashbin_insert(irttp->tsaps, (queue_t *) self, (int) self, NULL);
if (credit > TTP_MAX_QUEUE)
self->initial_credit = TTP_MAX_QUEUE;
@@ -217,7 +229,7 @@
{
struct tsap_cb *tsap;
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
ASSERT(self != NULL, return -1;);
ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
@@ -226,11 +238,11 @@
if (self->connected) {
/* Check if disconnect is not pending */
if (!self->disconnect_pend) {
- DEBUG(0, __FUNCTION__ "(), TSAP still connected!\n");
+ IRDA_DEBUG(0, __FUNCTION__ "(), TSAP still connected!\n");
irttp_disconnect_request(self, NULL, P_NORMAL);
}
self->close_pend = TRUE;
- irttp_start_todo_timer(self, 100);
+ irttp_start_todo_timer(self, 1*HZ);
return 0; /* Will be back! */
}
@@ -262,16 +274,16 @@
ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
ASSERT(skb != NULL, return -1;);
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
/* Check that nothing bad happens */
if ((skb->len == 0) || (!self->connected)) {
- DEBUG(1, __FUNCTION__ "(), No data, or not connected\n");
+ IRDA_DEBUG(1, __FUNCTION__ "(), No data, or not connected\n");
return -1;
}
if (skb->len > self->max_seg_size) {
- DEBUG(1, __FUNCTION__ "(), UData is to large for IrLAP!\n");
+ IRDA_DEBUG(1, __FUNCTION__ "(), UData is to large for IrLAP!\n");
return -1;
}
@@ -291,13 +303,9 @@
{
__u8 *frame;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
- ASSERT(skb != NULL, return -1;);
-
/* Check that nothing bad happens */
if ((skb->len == 0) || (!self->connected)) {
- ERROR(__FUNCTION__ "(), No data, or not connected\n");
+ WARNING(__FUNCTION__ "(), No data, or not connected\n");
return -ENOTCONN;
}
@@ -316,7 +324,7 @@
* TxMaxSduSize
*/
if ((self->tx_max_sdu_size != 0) &&
- (self->tx_max_sdu_size != SAR_UNBOUND) &&
+ (self->tx_max_sdu_size != TTP_SAR_UNBOUND) &&
(skb->len > self->tx_max_sdu_size))
{
ERROR(__FUNCTION__ "(), SAR enabled, "
@@ -355,7 +363,7 @@
/* Check if we can accept more data from client */
if ((!self->tx_sdu_busy) &&
- (skb_queue_len(&self->tx_queue) > HIGH_THRESHOLD)) {
+ (skb_queue_len(&self->tx_queue) > TTP_HIGH_THRESHOLD)) {
/* Tx queue filling up, so stop client */
self->tx_sdu_busy = TRUE;
@@ -375,25 +383,36 @@
/*
* Function irttp_run_tx_queue (self)
*
- * If possible, transmit a frame queued for transmission.
+ * Transmit packets queued for transmission (if possible)
*
*/
static void irttp_run_tx_queue(struct tsap_cb *self)
{
- struct sk_buff *skb = NULL;
+ struct sk_buff *skb;
unsigned long flags;
int n;
if (irda_lock(&self->tx_queue_lock) == FALSE)
return;
- while ((self->send_credit > 0) && !skb_queue_empty(&self->tx_queue)) {
- skb = skb_dequeue(&self->tx_queue);
- ASSERT(skb != NULL, return;);
-
- /* Make room for TTP header */
- ASSERT(skb_headroom(skb) >= TTP_HEADER, return;);
-
+ /* Try to send out frames as long as we have credits */
+ while ((self->send_credit > 0) &&
+ (skb = skb_dequeue(&self->tx_queue)))
+ {
+ /*
+ * Make sure we don't flood IrLAP with frames just because
+ * the remote device has given us a lot of credits
+ */
+ if (irlmp_get_lap_tx_queue_len(self->lsap) > LAP_MAX_QUEUE) {
+ /* Re-queue packet */
+ skb_queue_head(&self->tx_queue, skb);
+
+ /* Try later. Maybe IrLAP could notify us? */
+ irttp_start_todo_timer(self, MSECS_TO_JIFFIES(10));
+
+ break;
+ }
+
/*
* Since we can transmit and receive frames concurrently,
* the code below is a critical region and we must assure that
@@ -425,7 +444,7 @@
/* Check if we can accept more frames from client */
if ((self->tx_sdu_busy) &&
- (skb_queue_len(&self->tx_queue) < LOW_THRESHOLD))
+ (skb_queue_len(&self->tx_queue) < TTP_LOW_THRESHOLD))
{
self->tx_sdu_busy = FALSE;
@@ -435,9 +454,7 @@
FLOW_START);
}
}
-
- /* Reset lock */
- self->tx_queue_lock = 0;
+ self->tx_queue_lock = 0; /* Reset lock */
}
/*
@@ -455,8 +472,8 @@
ASSERT(self != NULL, return;);
ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
- DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n",
- self->send_credit, self->avail_credit, self->remote_credit);
+ IRDA_DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n",
+ self->send_credit, self->avail_credit, self->remote_credit);
/* Give credit to peer */
tx_skb = dev_alloc_skb(64);
@@ -503,7 +520,7 @@
{
struct tsap_cb *self;
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
self = (struct tsap_cb *) instance;
@@ -512,16 +529,18 @@
ASSERT(skb != NULL, return -1;);
/* Just pass data to layer above */
- if (self->notify.udata_indication) {
- self->notify.udata_indication(self->notify.instance, self, skb);
- }
+ if (self->notify.udata_indication)
+ self->notify.udata_indication(self->notify.instance, self,skb);
+ else
+ dev_kfree_skb(skb);
+
self->stats.rx_packets++;
return 0;
}
/*
- * Function irttp_data_indication (handle, skb)
+ * Function irttp_data_indication (instance, sap, skb)
*
* Receive segment from IrLMP.
*
@@ -534,20 +553,15 @@
self = (struct tsap_cb *) instance;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
-
n = skb->data[0] & 0x7f; /* Extract the credits */
self->stats.rx_packets++;
/*
- * Data or dataless frame? Dataless frames only contain the
- * TTP_HEADER
+ * Data or dataless packet? Dataless frames contains only the
+ * TTP_HEADER.
*/
- if (skb->len == 1)
- self->send_credit += n; /* Dataless flowdata TTP-PDU */
- else {
+ if (skb->len > 1) {
/* Deal with inbound credit */
self->send_credit += n;
self->remote_credit--;
@@ -557,7 +571,10 @@
* more bit, so the defragment routing knows what to do
*/
skb_queue_tail(&self->rx_queue, skb);
- }
+ } else {
+ self->send_credit += n; /* Dataless flowdata TTP-PDU */
+ dev_kfree_skb(skb);
+ }
irttp_run_rx_queue(self);
@@ -565,18 +582,22 @@
* Give avay some credits to peer?
*/
if ((skb_queue_empty(&self->tx_queue)) &&
- (self->remote_credit < LOW_THRESHOLD) &&
+ (self->remote_credit < TTP_LOW_THRESHOLD) &&
(self->avail_credit > 0))
{
/* Schedule to start immediately after this thread */
irttp_start_todo_timer(self, 0);
+ /*irttp_give_credit(self);*/
}
-
- /* If peer has given us some credites and we didn't have anyone
- * from before, the we need to shedule the tx queue?
+
+ /*
+ * If the peer device has given us some credits and we didn't have
+ * anyone from before, the we need to shedule the tx queue?
*/
- if (self->send_credit == n)
+ if (self->send_credit == n) {
+ /*irttp_run_tx_queue(self);*/
irttp_start_todo_timer(self, 0);
+ }
return 0;
}
@@ -589,24 +610,24 @@
*/
void irttp_flow_request(struct tsap_cb *self, LOCAL_FLOW flow)
{
- DEBUG(1, __FUNCTION__ "()\n");
+ IRDA_DEBUG(1, __FUNCTION__ "()\n");
ASSERT(self != NULL, return;);
ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
switch (flow) {
case FLOW_STOP:
- DEBUG(1, __FUNCTION__ "(), flow stop\n");
+ IRDA_DEBUG(1, __FUNCTION__ "(), flow stop\n");
self->rx_sdu_busy = TRUE;
break;
case FLOW_START:
- DEBUG(1, __FUNCTION__ "(), flow start\n");
+ IRDA_DEBUG(1, __FUNCTION__ "(), flow start\n");
self->rx_sdu_busy = FALSE;
irttp_run_rx_queue(self);
break;
default:
- DEBUG(1, __FUNCTION__ "(), Unknown flow command!\n");
+ IRDA_DEBUG(1, __FUNCTION__ "(), Unknown flow command!\n");
}
}
@@ -625,11 +646,14 @@
__u8 *frame;
__u8 n;
- DEBUG(4, __FUNCTION__ "(), max_sdu_size=%d\n", max_sdu_size);
+ IRDA_DEBUG(4, __FUNCTION__ "(), max_sdu_size=%d\n", max_sdu_size);
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+ ASSERT(self != NULL, return -EBADR;);
+ ASSERT(self->magic == TTP_TSAP_MAGIC, return -EBADR;);
+ if (self->connected)
+ return -EISCONN;
+
/* Any userdata supplied? */
if (userdata == NULL) {
skb = dev_alloc_skb(64);
@@ -705,17 +729,16 @@
*
*/
static void irttp_connect_confirm(void *instance, void *sap,
- struct qos_info *qos,
- __u32 max_seg_size, __u8 max_header_size,
- struct sk_buff *skb)
+ struct qos_info *qos, __u32 max_seg_size,
+ __u8 max_header_size, struct sk_buff *skb)
{
struct tsap_cb *self;
int parameters;
- __u8 *frame;
- __u8 plen, pi, pl;
+ int ret;
+ __u8 plen;
__u8 n;
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
self = (struct tsap_cb *) instance;
@@ -723,7 +746,7 @@
ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
ASSERT(skb != NULL, return;);
- self->max_seg_size = max_seg_size;
+ self->max_seg_size = max_seg_size - TTP_HEADER;
self->max_header_size = max_header_size + TTP_HEADER;
/*
@@ -731,63 +754,53 @@
* negotiated QoS for the link.
*/
if (qos) {
- DEBUG(4, "IrTTP, Negotiated BAUD_RATE: %02x\n",
+ IRDA_DEBUG(4, "IrTTP, Negotiated BAUD_RATE: %02x\n",
qos->baud_rate.bits);
- DEBUG(4, "IrTTP, Negotiated BAUD_RATE: %d bps.\n",
+ IRDA_DEBUG(4, "IrTTP, Negotiated BAUD_RATE: %d bps.\n",
qos->baud_rate.value);
}
- frame = skb->data;
- n = frame[0] & 0x7f;
+ n = skb->data[0] & 0x7f;
- DEBUG(4, __FUNCTION__ "(), Initial send_credit=%d\n", n);
+ IRDA_DEBUG(4, __FUNCTION__ "(), Initial send_credit=%d\n", n);
self->send_credit = n;
self->tx_max_sdu_size = 0;
self->connected = TRUE;
- parameters = frame[0] & 0x80;
+ parameters = skb->data[0] & 0x80;
ASSERT(skb->len >= TTP_HEADER, return;);
skb_pull(skb, TTP_HEADER);
-
+
if (parameters) {
- plen = frame[1];
- pi = frame[2];
- pl = frame[3];
-
- switch (pl) {
- case 1:
- self->tx_max_sdu_size = *(frame+4);
- break;
- case 2:
- self->tx_max_sdu_size =
- be16_to_cpu(get_unaligned((__u16 *)(frame+4)));
- break;
- case 4:
- self->tx_max_sdu_size =
- be32_to_cpu(get_unaligned((__u32 *)(frame+4)));
- break;
- default:
- printk(KERN_ERR __FUNCTION__
- "() illegal value length for max_sdu_size!\n");
- self->tx_max_sdu_size = 0;
- };
+ plen = skb->data[0];
- DEBUG(4, __FUNCTION__ "(), RxMaxSduSize=%d\n",
- self->tx_max_sdu_size);
-
+ ret = irda_param_extract_all(self, skb->data+1,
+ IRDA_MIN(skb->len-1, plen),
+ ¶m_info);
+
+ /* Any errors in the parameter list? */
+ if (ret < 0) {
+ WARNING(__FUNCTION__
+ "(), error extracting parameters\n");
+ dev_kfree_skb(skb);
+
+ /* Do not accept this connection attempt */
+ return;
+ }
/* Remove parameters */
- ASSERT(skb->len >= (plen+1), return;);
- skb_pull(skb, plen+1);
+ skb_pull(skb, IRDA_MIN(skb->len, plen+1));
}
- DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n",
+ IRDA_DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n",
self->send_credit, self->avail_credit, self->remote_credit);
+ IRDA_DEBUG(2, __FUNCTION__ "(), MaxSduSize=%d\n", self->tx_max_sdu_size);
+
if (self->notify.connect_confirm) {
self->notify.connect_confirm(self->notify.instance, self, qos,
- self->tx_max_sdu_size,
+ self->tx_max_sdu_size,
self->max_header_size, skb);
}
}
@@ -805,8 +818,8 @@
struct tsap_cb *self;
struct lsap_cb *lsap;
int parameters;
- __u8 *frame;
- __u8 plen, pi, pl;
+ int ret;
+ __u8 plen;
__u8 n;
self = (struct tsap_cb *) instance;
@@ -817,65 +830,51 @@
lsap = (struct lsap_cb *) sap;
- self->max_seg_size = max_seg_size;
-
+ self->max_seg_size = max_seg_size - TTP_HEADER;;
self->max_header_size = max_header_size+TTP_HEADER;
- DEBUG(4, __FUNCTION__ "(), TSAP sel=%02x\n", self->stsap_sel);
+ IRDA_DEBUG(4, __FUNCTION__ "(), TSAP sel=%02x\n", self->stsap_sel);
/* Need to update dtsap_sel if its equal to LSAP_ANY */
self->dtsap_sel = lsap->dlsap_sel;
- frame = skb->data;
- n = frame[0] & 0x7f;
+ n = skb->data[0] & 0x7f;
self->send_credit = n;
self->tx_max_sdu_size = 0;
- parameters = frame[0] & 0x80;
+ parameters = skb->data[0] & 0x80;
ASSERT(skb->len >= TTP_HEADER, return;);
skb_pull(skb, TTP_HEADER);
-
+
if (parameters) {
- DEBUG(3, __FUNCTION__ "(), Contains parameters!\n");
- plen = frame[1];
- pi = frame[2];
- pl = frame[3];
-
- switch (pl) {
- case 1:
- self->tx_max_sdu_size = frame[4];
- break;
- case 2:
- self->tx_max_sdu_size =
- be16_to_cpu(get_unaligned((__u16 *)(frame+4)));
- break;
- case 4:
- self->tx_max_sdu_size =
- be32_to_cpu(get_unaligned((__u32 *)(frame+4)));
- break;
- default:
- printk(KERN_ERR __FUNCTION__
- "() illegal value length for max_sdu_size!\n");
- self->tx_max_sdu_size = 0;
- };
+ plen = skb->data[0];
- /* Remove parameters */
- ASSERT(skb->len >= (plen+1), return;);
- skb_pull(skb, plen+1);
+ ret = irda_param_extract_all(self, skb->data+1,
+ IRDA_MIN(skb->len-1, plen),
+ ¶m_info);
+
+ /* Any errors in the parameter list? */
+ if (ret < 0) {
+ WARNING(__FUNCTION__
+ "(), error extracting parameters\n");
+ dev_kfree_skb(skb);
+
+ /* Do not accept this connection attempt */
+ return;
+ }
- DEBUG(3, __FUNCTION__ "(), MaxSduSize=%d\n",
- self->tx_max_sdu_size);
+ /* Remove parameters */
+ skb_pull(skb, IRDA_MIN(skb->len, plen+1));
}
- DEBUG(4, __FUNCTION__ "(), initial send_credit=%d\n", n);
-
if (self->notify.connect_indication) {
self->notify.connect_indication(self->notify.instance, self,
- qos, self->rx_max_sdu_size,
+ qos, self->tx_max_sdu_size,
self->max_header_size, skb);
- }
+ } else
+ dev_kfree_skb(skb);
}
/*
@@ -885,24 +884,25 @@
* IrLMP!
*
*/
-void irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,
- struct sk_buff *userdata)
+int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,
+ struct sk_buff *userdata)
{
struct sk_buff *skb;
__u8 *frame;
+ int ret;
__u8 n;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+ ASSERT(self != NULL, return -1;);
+ ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
- DEBUG(4, __FUNCTION__ "(), Source TSAP selector=%02x\n",
- self->stsap_sel);
+ IRDA_DEBUG(4, __FUNCTION__ "(), Source TSAP selector=%02x\n",
+ self->stsap_sel);
/* Any userdata supplied? */
if (userdata == NULL) {
skb = dev_alloc_skb(64);
if (!skb)
- return;
+ return -ENOMEM;
/* Reserve space for MUX_CONTROL and LAP header */
skb_reserve(skb, TTP_MAX_HEADER);
@@ -912,7 +912,7 @@
* Check that the client has reserved enough space for
* headers
*/
- ASSERT(skb_headroom(skb) >= TTP_MAX_HEADER, return;);
+ ASSERT(skb_headroom(skb) >= TTP_MAX_HEADER, return -1;);
}
self->avail_credit = 0;
@@ -935,13 +935,17 @@
/* SAR enabled? */
if (max_sdu_size > 0) {
ASSERT(skb_headroom(skb) >= (TTP_MAX_HEADER+TTP_SAR_HEADER),
- return;);
+ return -1;);
/* Insert TTP header with SAR parameters */
frame = skb_push(skb, TTP_HEADER+TTP_SAR_HEADER);
frame[0] = TTP_PARAMETERS | n;
frame[1] = 0x04; /* Length */
+
+ /* irda_param_insert(self, IRTTP_MAX_SDU_SIZE, frame+1, */
+/* TTP_SAR_HEADER, ¶m_info) */
+
frame[2] = 0x01; /* MaxSduSize */
frame[3] = 0x02; /* Value length */
@@ -954,7 +958,9 @@
frame[0] = n & 0x7f;
}
- irlmp_connect_response(self->lsap, skb);
+ ret = irlmp_connect_response(self->lsap, skb);
+
+ return ret;
}
/*
@@ -967,15 +973,15 @@
{
struct tsap_cb *new;
- DEBUG(1, __FUNCTION__ "()\n");
+ IRDA_DEBUG(1, __FUNCTION__ "()\n");
if (!hashbin_find(irttp->tsaps, (int) orig, NULL)) {
- DEBUG(0, __FUNCTION__ "(), unable to find TSAP\n");
+ IRDA_DEBUG(0, __FUNCTION__ "(), unable to find TSAP\n");
return NULL;
}
new = kmalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
if (!new) {
- DEBUG(0, __FUNCTION__ "(), unable to kmalloc\n");
+ IRDA_DEBUG(0, __FUNCTION__ "(), unable to kmalloc\n");
return NULL;
}
/* Dup */
@@ -990,7 +996,7 @@
skb_queue_head_init(&new->tx_queue);
skb_queue_head_init(&new->rx_fragments);
- hashbin_insert(irttp->tsaps, (QUEUE *) new, (int) new, NULL);
+ hashbin_insert(irttp->tsaps, (queue_t *) new, (int) new, NULL);
return new;
}
@@ -1002,32 +1008,31 @@
* segments, if any, will be deallocated first
*
*/
-void irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata,
- int priority)
+int irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata,
+ int priority)
{
struct sk_buff *skb;
+ int ret;
- DEBUG(2, __FUNCTION__ "()\n");
-
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+ ASSERT(self != NULL, return -1;);
+ ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
/* Already disconnected? */
if (!self->connected) {
- DEBUG(4, __FUNCTION__ "(), already disconnected!\n");
- return;
+ IRDA_DEBUG(4, __FUNCTION__ "(), already disconnected!\n");
+ return -1;
}
/* Disconnect already pending? */
if (self->disconnect_pend) {
- DEBUG(1, __FUNCTION__ "(), disconnect already pending\n");
+ IRDA_DEBUG(1, __FUNCTION__ "(), disconnect already pending\n");
if (userdata) {
dev_kfree_skb(userdata);
}
/* Try to make some progress */
irttp_run_rx_queue(self);
- return;
+ return -1;
}
/*
@@ -1035,7 +1040,7 @@
*/
if (skb_queue_len(&self->tx_queue) > 0) {
if (priority == P_HIGH) {
- DEBUG(1, __FUNCTION__ "High priority!!()\n" );
+ IRDA_DEBUG(1, __FUNCTION__ "High priority!!()\n" );
/*
* No need to send the queued data, if we are
@@ -1057,18 +1062,18 @@
irttp_run_tx_queue(self);
- irttp_start_todo_timer(self, 100);
- return;
+ irttp_start_todo_timer(self, MSECS_TO_JIFFIES(1000));
+ return -1;
}
}
- DEBUG(1, __FUNCTION__ "(), Disconnecting ...\n");
+ IRDA_DEBUG(1, __FUNCTION__ "(), Disconnecting ...\n");
self->connected = FALSE;
if (!userdata) {
skb = dev_alloc_skb(64);
if (!skb)
- return;
+ return -ENOMEM;
/*
* Reserve space for MUX and LAP header
@@ -1077,7 +1082,9 @@
userdata = skb;
}
- irlmp_disconnect_request(self->lsap, userdata);
+ ret = irlmp_disconnect_request(self->lsap, userdata);
+
+ return ret;
}
/*
@@ -1087,11 +1094,11 @@
*
*/
void irttp_disconnect_indication(void *instance, void *sap, LM_REASON reason,
- struct sk_buff *userdata)
+ struct sk_buff *skb)
{
struct tsap_cb *self;
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
self = (struct tsap_cb *) instance;
@@ -1100,11 +1107,22 @@
self->connected = FALSE;
- if (!self->notify.disconnect_indication)
+ /* Check if client has already tried to close the TSAP */
+ if (self->close_pend) {
+ irttp_close_tsap(self);
return;
+ }
- self->notify.disconnect_indication(self->notify.instance, self, reason,
- userdata);
+ /* No need to notify the client if has already tried to disconnect */
+ if (self->disconnect_pend)
+ return;
+
+ if (self->notify.disconnect_indication)
+ self->notify.disconnect_indication(self->notify.instance, self,
+ reason, skb);
+ else
+ if (skb)
+ dev_kfree_skb(skb);
}
/*
@@ -1118,6 +1136,12 @@
{
int err;
+ /* Check if client has already tried to close the TSAP */
+ if (self->close_pend || self->disconnect_pend) {
+ dev_kfree_skb(skb);
+ return;
+ }
+
err = self->notify.data_indication(self->notify.instance, self, skb);
/* Usually the layer above will notify that it's input queue is
@@ -1126,7 +1150,7 @@
* give an error back
*/
if (err == -ENOMEM) {
- DEBUG(0, __FUNCTION__ "() requeueing skb!\n");
+ IRDA_DEBUG(0, __FUNCTION__ "() requeueing skb!\n");
/* Make sure we take a break */
self->rx_sdu_busy = TRUE;
@@ -1151,8 +1175,8 @@
struct sk_buff *skb;
int more = 0;
- DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n",
- self->send_credit, self->avail_credit, self->remote_credit);
+ IRDA_DEBUG(2, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n",
+ self->send_credit, self->avail_credit, self->remote_credit);
if (irda_lock(&self->rx_queue_lock) == FALSE)
return;
@@ -1177,7 +1201,7 @@
* immediately. This can be requested by clients that
* implements byte streams without any message boundaries
*/
- if (self->rx_max_sdu_size == SAR_DISABLE) {
+ if (self->rx_max_sdu_size == TTP_SAR_DISABLE) {
irttp_do_data_indication(self, skb);
self->rx_sdu_size = 0;
@@ -1191,7 +1215,7 @@
* limits of the maximum size of the rx_sdu
*/
if (self->rx_sdu_size <= self->rx_max_sdu_size) {
- DEBUG(4, __FUNCTION__ "(), queueing frag\n");
+ IRDA_DEBUG(4, __FUNCTION__ "(), queueing frag\n");
skb_queue_tail(&self->rx_fragments, skb);
} else {
/* Free the part of the SDU that is too big */
@@ -1203,7 +1227,7 @@
* This is the last fragment, so time to reassemble!
*/
if ((self->rx_sdu_size <= self->rx_max_sdu_size) ||
- (self->rx_max_sdu_size == SAR_UNBOUND))
+ (self->rx_max_sdu_size == TTP_SAR_UNBOUND))
{
/*
* A little optimizing. Only queue the fragment if
@@ -1221,7 +1245,7 @@
/* Now we can deliver the reassembled skb */
irttp_do_data_indication(self, skb);
} else {
- DEBUG(1, __FUNCTION__ "(), Truncated frame\n");
+ IRDA_DEBUG(1, __FUNCTION__ "(), Truncated frame\n");
/* Free the part of the SDU that is too big */
dev_kfree_skb(skb);
@@ -1246,7 +1270,7 @@
{
struct sk_buff* skb;
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
ASSERT(self != NULL, return;);
ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
@@ -1279,10 +1303,10 @@
ASSERT(self != NULL, return NULL;);
ASSERT(self->magic == TTP_TSAP_MAGIC, return NULL;);
- DEBUG(4, __FUNCTION__ "(), self->rx_sdu_size=%d\n",
- self->rx_sdu_size);
+ IRDA_DEBUG(2, __FUNCTION__ "(), self->rx_sdu_size=%d\n",
+ self->rx_sdu_size);
- skb = dev_alloc_skb(self->rx_sdu_size);
+ skb = dev_alloc_skb(TTP_HEADER + self->rx_sdu_size);
if (!skb)
return NULL;
@@ -1302,11 +1326,12 @@
dev_kfree_skb(frag);
}
- DEBUG(4, __FUNCTION__ "(), frame len=%d\n", n);
- /* Set the new length */
+ IRDA_DEBUG(2, __FUNCTION__ "(), frame len=%d\n", n);
- DEBUG(4, __FUNCTION__ "(), rx_sdu_size=%d\n", self->rx_sdu_size);
+ IRDA_DEBUG(2, __FUNCTION__ "(), rx_sdu_size=%d\n", self->rx_sdu_size);
ASSERT(n <= self->rx_sdu_size, return NULL;);
+
+ /* Set the new length */
skb_trim(skb, n);
self->rx_sdu_size = 0;
@@ -1325,7 +1350,7 @@
struct sk_buff *frag;
__u8 *frame;
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
ASSERT(self != NULL, return;);
ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
@@ -1334,22 +1359,9 @@
/*
* Split frame into a number of segments
*/
- while (skb->len > 0) {
- /*
- * Instead of making the last segment, we just
- * queue what is left of the original skb
- */
- if (skb->len < self->max_seg_size) {
- DEBUG(4, __FUNCTION__
- "(), queuing last segment\n");
-
- frame = skb_push(skb, TTP_HEADER);
- frame[0] = 0x00; /* Clear more bit */
- skb_queue_tail(&self->tx_queue, skb);
-
- return;
- }
-
+ while (skb->len > self->max_seg_size) {
+ IRDA_DEBUG(2, __FUNCTION__ "(), fragmenting ...\n");
+
/* Make new segment */
frag = dev_alloc_skb(self->max_seg_size+self->max_header_size);
if (!frag)
@@ -1357,19 +1369,55 @@
skb_reserve(frag, self->max_header_size);
- /*
- * Copy data from the original skb into this fragment. We
- * first insert the TTP header with the more bit set
- */
- frame = skb_put(frag, self->max_seg_size+TTP_HEADER);
+ /* Copy data from the original skb into this fragment. */
+ memcpy(skb_put(frag, self->max_seg_size), skb->data,
+ self->max_seg_size);
+
+ /* Insert TTP header, with the more bit set */
+ frame = skb_push(frag, TTP_HEADER);
frame[0] = TTP_MORE;
- memcpy(frag->data+1, skb->data, self->max_seg_size);
/* Hide the copied data from the original skb */
skb_pull(skb, self->max_seg_size);
-
+
+ /* Queue fragment */
skb_queue_tail(&self->tx_queue, frag);
}
+ /* Queue what is left of the original skb */
+ IRDA_DEBUG(2, __FUNCTION__ "(), queuing last segment\n");
+
+ frame = skb_push(skb, TTP_HEADER);
+ frame[0] = 0x00; /* Clear more bit */
+
+ /* Queue fragment */
+ skb_queue_tail(&self->tx_queue, skb);
+}
+
+/*
+ * Function irttp_param_max_sdu_size (self, param)
+ *
+ * Handle the MaxSduSize parameter in the connect frames, this function
+ * will be called both when this parameter needs to be inserted into, and
+ * extracted from the connect frames
+ */
+static int irttp_param_max_sdu_size(void *instance, irda_param_t *param,
+ int get)
+{
+ struct tsap_cb *self;
+
+ self = (struct tsap_cb *) instance;
+
+ ASSERT(self != NULL, return -1;);
+ ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+
+ if (get)
+ param->pv.i = self->tx_max_sdu_size;
+ else
+ self->tx_max_sdu_size = param->pv.i;
+
+ IRDA_DEBUG(0, __FUNCTION__ "(), MaxSduSize=%d\n", param->pv.i);
+
+ return 0;
}
/*
@@ -1382,18 +1430,15 @@
{
struct tsap_cb *self = (struct tsap_cb *) data;
- DEBUG(4, __FUNCTION__ "()\n");
-
/* Check that we still exist */
- if (!self || self->magic != TTP_TSAP_MAGIC) {
+ if (!self || self->magic != TTP_TSAP_MAGIC)
return;
- }
-
+
irttp_run_rx_queue(self);
irttp_run_tx_queue(self);
-
+
/* Give avay some credits to peer? */
- if ((self->remote_credit < LOW_THRESHOLD) &&
+ if ((self->remote_credit < TTP_LOW_THRESHOLD) &&
(self->avail_credit > 0) && (skb_queue_empty(&self->tx_queue)))
{
irttp_give_credit(self);
@@ -1414,13 +1459,13 @@
irttp_disconnect_request(self, NULL, P_NORMAL);
} else {
/* Try again later */
- irttp_start_todo_timer(self, 100);
+ irttp_start_todo_timer(self, 1*HZ);
/* No reason to try and close now */
return;
}
}
-
+
/* Check if it's closing time */
if (self->close_pend)
irttp_close_tsap(self);
@@ -1442,7 +1487,7 @@
self->todo_timer.data = (unsigned long) self;
self->todo_timer.function = &irttp_todo_expired;
self->todo_timer.expires = jiffies + timeout;
-
+
add_timer(&self->todo_timer);
}
@@ -1467,42 +1512,40 @@
self = (struct tsap_cb *) hashbin_get_first(irttp->tsaps);
while (self != NULL) {
- if (!self || self->magic != TTP_TSAP_MAGIC) {
- DEBUG(1, "irttp_proc_read: bad ptr self\n");
+ if (!self || self->magic != TTP_TSAP_MAGIC)
return len;
- }
len += sprintf(buf+len, "TSAP %d, ", i++);
len += sprintf(buf+len, "stsap_sel: %02x, ",
- self->stsap_sel);
+ self->stsap_sel);
len += sprintf(buf+len, "dtsap_sel: %02x\n",
- self->dtsap_sel);
+ self->dtsap_sel);
len += sprintf(buf+len, " connected: %s, ",
- self->connected? "TRUE":"FALSE");
+ self->connected? "TRUE":"FALSE");
len += sprintf(buf+len, "avail credit: %d, ",
- self->avail_credit);
+ self->avail_credit);
len += sprintf(buf+len, "remote credit: %d, ",
- self->remote_credit);
+ self->remote_credit);
len += sprintf(buf+len, "send credit: %d\n",
- self->send_credit);
+ self->send_credit);
len += sprintf(buf+len, " tx packets: %d, ",
- self->stats.tx_packets);
+ self->stats.tx_packets);
len += sprintf(buf+len, "rx packets: %d, ",
- self->stats.rx_packets);
+ self->stats.rx_packets);
len += sprintf(buf+len, "tx_queue len: %d ",
- skb_queue_len(&self->tx_queue));
+ skb_queue_len(&self->tx_queue));
len += sprintf(buf+len, "rx_queue len: %d\n",
- skb_queue_len(&self->rx_queue));
+ skb_queue_len(&self->rx_queue));
len += sprintf(buf+len, " tx_sdu_busy: %s, ",
- self->tx_sdu_busy? "TRUE":"FALSE");
+ self->tx_sdu_busy? "TRUE":"FALSE");
len += sprintf(buf+len, "rx_sdu_busy: %s\n",
- self->rx_sdu_busy? "TRUE":"FALSE");
+ self->rx_sdu_busy? "TRUE":"FALSE");
len += sprintf(buf+len, " max_seg_size: %d, ",
- self->max_seg_size);
+ self->max_seg_size);
len += sprintf(buf+len, "tx_max_sdu_size: %d, ",
- self->tx_max_sdu_size);
+ self->tx_max_sdu_size);
len += sprintf(buf+len, "rx_max_sdu_size: %d\n",
- self->rx_max_sdu_size);
+ self->rx_max_sdu_size);
len += sprintf(buf+len, " Used by (%s)\n",
self->notify.name);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)