patch-2.4.23 linux-2.4.23/net/bluetooth/rfcomm/core.c
Next file: linux-2.4.23/net/bridge/br_forward.c
Previous file: linux-2.4.23/net/atm/svc.c
Back to the patch index
Back to the overall index
- Lines: 240
- Date:
2003-11-28 10:26:21.000000000 -0800
- Orig file:
linux-2.4.22/net/bluetooth/rfcomm/core.c
- Orig date:
2003-08-25 04:44:44.000000000 -0700
diff -urN linux-2.4.22/net/bluetooth/rfcomm/core.c linux-2.4.23/net/bluetooth/rfcomm/core.c
@@ -51,7 +51,7 @@
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/rfcomm.h>
-#define VERSION "1.0"
+#define VERSION "1.1"
#ifndef CONFIG_BLUEZ_RFCOMM_DEBUG
#undef BT_DBG
@@ -202,7 +202,7 @@
d->mtu = RFCOMM_DEFAULT_MTU;
d->v24_sig = RFCOMM_V24_RTC | RFCOMM_V24_RTR | RFCOMM_V24_DV;
- d->credits = RFCOMM_MAX_CREDITS;
+ d->cfc = RFCOMM_CFC_DISABLED;
d->rx_credits = RFCOMM_DEFAULT_CREDITS;
}
@@ -309,8 +309,8 @@
d->state = BT_CONFIG;
rfcomm_dlc_link(s, d);
- d->mtu = s->mtu;
- d->credits = s->credits;
+ d->mtu = s->mtu;
+ d->cfc = (s->cfc == RFCOMM_CFC_UNKNOWN) ? 0 : s->cfc;
if (s->state == BT_CONNECTED)
rfcomm_send_pn(s, 1, d);
@@ -410,7 +410,7 @@
{
BT_DBG("dlc %p state %ld", d, d->state);
- if (!d->credits) {
+ if (!d->cfc) {
d->v24_sig |= RFCOMM_V24_FC;
set_bit(RFCOMM_MSC_PENDING, &d->flags);
}
@@ -421,7 +421,7 @@
{
BT_DBG("dlc %p state %ld", d, d->state);
- if (!d->credits) {
+ if (!d->cfc) {
d->v24_sig &= ~RFCOMM_V24_FC;
set_bit(RFCOMM_MSC_PENDING, &d->flags);
}
@@ -474,8 +474,8 @@
s->state = state;
s->sock = sock;
- s->mtu = RFCOMM_DEFAULT_MTU;
- s->credits = RFCOMM_MAX_CREDITS;
+ s->mtu = RFCOMM_DEFAULT_MTU;
+ s->cfc = RFCOMM_CFC_UNKNOWN;
list_add(&s->list, &session_list);
@@ -746,7 +746,7 @@
pn->ack_timer = 0;
pn->max_retrans = 0;
- if (d->credits) {
+ if (s->cfc) {
pn->flow_ctrl = cr ? 0xf0 : 0xe0;
pn->credits = RFCOMM_DEFAULT_CREDITS;
} else {
@@ -853,6 +853,50 @@
return rfcomm_send_frame(s, buf, ptr - buf);
}
+static int rfcomm_send_fcoff(struct rfcomm_session *s, int cr)
+{
+ struct rfcomm_hdr *hdr;
+ struct rfcomm_mcc *mcc;
+ u8 buf[16], *ptr = buf;
+
+ BT_DBG("%p cr %d", s, cr);
+
+ hdr = (void *) ptr; ptr += sizeof(*hdr);
+ hdr->addr = __addr(s->initiator, 0);
+ hdr->ctrl = __ctrl(RFCOMM_UIH, 0);
+ hdr->len = __len8(sizeof(*mcc));
+
+ mcc = (void *) ptr; ptr += sizeof(*mcc);
+ mcc->type = __mcc_type(cr, RFCOMM_FCOFF);
+ mcc->len = __len8(0);
+
+ *ptr = __fcs(buf); ptr++;
+
+ return rfcomm_send_frame(s, buf, ptr - buf);
+}
+
+static int rfcomm_send_fcon(struct rfcomm_session *s, int cr)
+{
+ struct rfcomm_hdr *hdr;
+ struct rfcomm_mcc *mcc;
+ u8 buf[16], *ptr = buf;
+
+ BT_DBG("%p cr %d", s, cr);
+
+ hdr = (void *) ptr; ptr += sizeof(*hdr);
+ hdr->addr = __addr(s->initiator, 0);
+ hdr->ctrl = __ctrl(RFCOMM_UIH, 0);
+ hdr->len = __len8(sizeof(*mcc));
+
+ mcc = (void *) ptr; ptr += sizeof(*mcc);
+ mcc->type = __mcc_type(cr, RFCOMM_FCON);
+ mcc->len = __len8(0);
+
+ *ptr = __fcs(buf); ptr++;
+
+ return rfcomm_send_frame(s, buf, ptr - buf);
+}
+
static int rfcomm_send_test(struct rfcomm_session *s, int cr, u8 *pattern, int len)
{
struct socket *sock = s->sock;
@@ -1091,28 +1135,22 @@
static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn)
{
+ struct rfcomm_session *s = d->session;
+
BT_DBG("dlc %p state %ld dlci %d mtu %d fc 0x%x credits %d",
d, d->state, d->dlci, pn->mtu, pn->flow_ctrl, pn->credits);
- if (cr) {
- if (pn->flow_ctrl == 0xf0) {
- d->tx_credits = pn->credits;
- } else {
- set_bit(RFCOMM_TX_THROTTLED, &d->flags);
- d->credits = 0;
- }
+ if (pn->flow_ctrl == 0xf0 || pn->flow_ctrl == 0xe0) {
+ d->cfc = s->cfc = RFCOMM_CFC_ENABLED;
+ d->tx_credits = pn->credits;
} else {
- if (pn->flow_ctrl == 0xe0) {
- d->tx_credits = pn->credits;
- } else {
- set_bit(RFCOMM_TX_THROTTLED, &d->flags);
- d->credits = 0;
- }
+ d->cfc = s->cfc = RFCOMM_CFC_DISABLED;
+ set_bit(RFCOMM_TX_THROTTLED, &d->flags);
}
d->priority = pn->priority;
- d->mtu = btohs(pn->mtu);
+ d->mtu = s->mtu = btohs(pn->mtu);
return 0;
}
@@ -1302,7 +1340,7 @@
return 0;
if (cr) {
- if (msc->v24_sig & RFCOMM_V24_FC && !d->credits)
+ if (msc->v24_sig & RFCOMM_V24_FC && !d->cfc)
set_bit(RFCOMM_TX_THROTTLED, &d->flags);
else
clear_bit(RFCOMM_TX_THROTTLED, &d->flags);
@@ -1351,6 +1389,20 @@
rfcomm_recv_msc(s, cr, skb);
break;
+ case RFCOMM_FCOFF:
+ if (cr) {
+ set_bit(RFCOMM_TX_THROTTLED, &s->flags);
+ rfcomm_send_fcoff(s, 0);
+ }
+ break;
+
+ case RFCOMM_FCON:
+ if (cr) {
+ clear_bit(RFCOMM_TX_THROTTLED, &s->flags);
+ rfcomm_send_fcon(s, 0);
+ }
+ break;
+
case RFCOMM_TEST:
if (cr)
rfcomm_send_test(s, 0, skb->data, skb->len);
@@ -1379,7 +1431,7 @@
goto drop;
}
- if (pf && d->credits) {
+ if (pf && d->cfc) {
u8 credits = *(u8 *) skb->data; skb_pull(skb, 1);
d->tx_credits += credits;
@@ -1484,20 +1536,20 @@
struct sk_buff *skb;
int err;
- BT_DBG("dlc %p state %ld credits %d rx_credits %d tx_credits %d",
- d, d->state, d->credits, d->rx_credits, d->tx_credits);
+ BT_DBG("dlc %p state %ld cfc %d rx_credits %d tx_credits %d",
+ d, d->state, d->cfc, d->rx_credits, d->tx_credits);
/* Send pending MSC */
if (test_and_clear_bit(RFCOMM_MSC_PENDING, &d->flags))
rfcomm_send_msc(d->session, 1, d->dlci, d->v24_sig);
- if (d->credits) {
+ if (d->cfc) {
/* CFC enabled.
* Give them some credits */
if (!test_bit(RFCOMM_RX_THROTTLED, &d->flags) &&
- d->rx_credits <= (d->credits >> 2)) {
- rfcomm_send_credits(d->session, d->addr, d->credits - d->rx_credits);
- d->rx_credits = d->credits;
+ d->rx_credits <= (d->cfc >> 2)) {
+ rfcomm_send_credits(d->session, d->addr, d->cfc - d->rx_credits);
+ d->rx_credits = d->cfc;
}
} else {
/* CFC disabled.
@@ -1518,7 +1570,7 @@
d->tx_credits--;
}
- if (d->credits && !d->tx_credits) {
+ if (d->cfc && !d->tx_credits) {
/* We're out of TX credits.
* Set TX_THROTTLED flag to avoid unnesary wakeups by dlc_send. */
set_bit(RFCOMM_TX_THROTTLED, &d->flags);
@@ -1541,6 +1593,9 @@
continue;
}
+ if (test_bit(RFCOMM_TX_THROTTLED, &s->flags))
+ continue;
+
if ((d->state == BT_CONNECTED || d->state == BT_DISCONN) &&
d->mscex == RFCOMM_MSCEX_OK)
rfcomm_process_tx(d);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)