patch-2.4.22 linux-2.4.22/net/bluetooth/rfcomm/core.c

Next file: linux-2.4.22/net/bluetooth/rfcomm/sock.c
Previous file: linux-2.4.22/net/bluetooth/l2cap.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.21/net/bluetooth/rfcomm/core.c linux-2.4.22/net/bluetooth/rfcomm/core.c
@@ -198,6 +198,7 @@
 
 	d->state      = BT_OPEN;
 	d->flags      = 0;
+	d->mscex      = 0;
 	d->mtu        = RFCOMM_DEFAULT_MTU;
 	d->v24_sig    = RFCOMM_V24_RTC | RFCOMM_V24_RTR | RFCOMM_V24_DV;
 
@@ -274,13 +275,13 @@
 static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, u8 channel)
 {
 	struct rfcomm_session *s;
-	u8 dlci = __dlci(0, channel);
 	int err = 0;
+	u8 dlci;
 
-	BT_DBG("dlc %p state %ld %s %s channel %d dlci %d", 
-			d, d->state, batostr(src), batostr(dst), channel, dlci);
+	BT_DBG("dlc %p state %ld %s %s channel %d", 
+			d, d->state, batostr(src), batostr(dst), channel);
 
-	if (dlci < 1 || dlci > 62)
+	if (channel < 1 || channel > 30)
 		return -EINVAL;
 
 	if (d->state != BT_OPEN && d->state != BT_CLOSED)
@@ -293,16 +294,19 @@
 			return err;
 	}
 
+	dlci = __dlci(!s->initiator, channel);
+
 	/* Check if DLCI already exists */
 	if (rfcomm_dlc_get(s, dlci))
 		return -EBUSY;
 
 	rfcomm_dlc_clear_state(d);
 
-	d->dlci    = dlci;
-	d->addr    = __addr(s->initiator, dlci);
+	d->dlci     = dlci;
+	d->addr     = __addr(s->initiator, dlci);
+	d->priority = 7;
 
-	d->state   = BT_CONFIG;
+	d->state    = BT_CONFIG;
 	rfcomm_dlc_link(s, d);
 
 	d->mtu     = s->mtu;
@@ -707,7 +711,7 @@
 	hdr->len  = __len8(sizeof(*mcc) + 1);
 
 	mcc = (void *) ptr; ptr += sizeof(*mcc);
-	mcc->type = __mcc_type(s->initiator, RFCOMM_NSC);
+	mcc->type = __mcc_type(cr, RFCOMM_NSC);
 	mcc->len  = __len8(1);
 
 	/* Type that we didn't like */
@@ -733,12 +737,12 @@
 	hdr->len  = __len8(sizeof(*mcc) + sizeof(*pn));
 
 	mcc = (void *) ptr; ptr += sizeof(*mcc);
-	mcc->type = __mcc_type(s->initiator, RFCOMM_PN);
+	mcc->type = __mcc_type(cr, RFCOMM_PN);
 	mcc->len  = __len8(sizeof(*pn));
 
 	pn = (void *) ptr; ptr += sizeof(*pn);
 	pn->dlci        = d->dlci;
-	pn->priority    = 0;
+	pn->priority    = d->priority;
 	pn->ack_timer   = 0;
 	pn->max_retrans = 0;
 
@@ -842,7 +846,7 @@
 
 	msc = (void *) ptr; ptr += sizeof(*msc);
 	msc->dlci    = __addr(1, dlci);
-	msc->v24_sig = v24_sig;
+	msc->v24_sig = v24_sig | 0x01;
 
 	*ptr = __fcs(buf); ptr++;
 
@@ -1076,6 +1080,8 @@
 		d->state = BT_CONNECTED;
 		d->state_change(d, 0);
 		rfcomm_dlc_unlock(d);
+
+		rfcomm_send_msc(s, 1, dlci, d->v24_sig);
 	} else {
 		rfcomm_send_dm(s, dlci);
 	}
@@ -1095,8 +1101,6 @@
 			set_bit(RFCOMM_TX_THROTTLED, &d->flags);
 			d->credits = 0;
 		}
-
-		d->mtu = btohs(pn->mtu);
 	} else {
 		if (pn->flow_ctrl == 0xe0) {
 			d->tx_credits = pn->credits;
@@ -1104,10 +1108,12 @@
 			set_bit(RFCOMM_TX_THROTTLED, &d->flags);
 			d->credits = 0;
 		}
-
-		d->mtu = btohs(pn->mtu);
 	}
 
+	d->priority = pn->priority;
+
+	d->mtu = btohs(pn->mtu);
+
 	return 0;
 }
 
@@ -1133,7 +1139,7 @@
 			switch (d->state) {
 			case BT_CONFIG:
 				rfcomm_apply_pn(d, cr, pn);
-				
+
 				d->state = BT_CONNECT;
 				rfcomm_send_sabm(s, d->dlci);
 				break;
@@ -1144,7 +1150,7 @@
 
 		if (!cr)
 			return 0;
-		
+
 		/* PN request for non existing DLC.
 		 * Assume incomming connection. */
 		if (rfcomm_connect_ind(s, channel, &d)) {
@@ -1153,7 +1159,7 @@
 			rfcomm_dlc_link(s, d);
 
 			rfcomm_apply_pn(d, cr, pn);
-			
+
 			d->state = BT_OPEN;
 			rfcomm_send_pn(s, 0, d);
 		} else {
@@ -1198,6 +1204,14 @@
 	}
 	/* check for sane values: ignore/accept bit_rate, 8 bits, 1 stop bit, no parity,
 	                          no flow control lines, normal XON/XOFF chars */
+	if (rpn->param_mask & RFCOMM_RPN_PM_BITRATE) {
+		bit_rate = rpn->bit_rate;
+		if (bit_rate != RFCOMM_RPN_BR_115200) {
+			BT_DBG("RPN bit rate mismatch 0x%x", bit_rate);
+			bit_rate = RFCOMM_RPN_BR_115200;
+			rpn_mask ^= RFCOMM_RPN_PM_BITRATE;
+		}
+	}
 	if (rpn->param_mask & RFCOMM_RPN_PM_DATA) {
 		data_bits = __get_rpn_data_bits(rpn->line_settings);
 		if (data_bits != RFCOMM_RPN_DATA_8) {
@@ -1223,23 +1237,26 @@
 		}
 	}
 	if (rpn->param_mask & RFCOMM_RPN_PM_FLOW) {
-		if (rpn->flow_ctrl != RFCOMM_RPN_FLOW_NONE) {
-			BT_DBG("RPN flow ctrl mismatch 0x%x", rpn->flow_ctrl);
-			rpn->flow_ctrl = RFCOMM_RPN_FLOW_NONE;
+		flow_ctrl = rpn->flow_ctrl;
+		if (flow_ctrl != RFCOMM_RPN_FLOW_NONE) {
+			BT_DBG("RPN flow ctrl mismatch 0x%x", flow_ctrl);
+			flow_ctrl = RFCOMM_RPN_FLOW_NONE;
 			rpn_mask ^= RFCOMM_RPN_PM_FLOW;
 		}
 	}
 	if (rpn->param_mask & RFCOMM_RPN_PM_XON) {
-		if (rpn->xon_char != RFCOMM_RPN_XON_CHAR) {
-			BT_DBG("RPN XON char mismatch 0x%x", rpn->xon_char);
-			rpn->xon_char = RFCOMM_RPN_XON_CHAR;
+		xon_char = rpn->xon_char;
+		if (xon_char != RFCOMM_RPN_XON_CHAR) {
+			BT_DBG("RPN XON char mismatch 0x%x", xon_char);
+			xon_char = RFCOMM_RPN_XON_CHAR;
 			rpn_mask ^= RFCOMM_RPN_PM_XON;
 		}
 	}
 	if (rpn->param_mask & RFCOMM_RPN_PM_XOFF) {
-		if (rpn->xoff_char != RFCOMM_RPN_XOFF_CHAR) {
-			BT_DBG("RPN XOFF char mismatch 0x%x", rpn->xoff_char);
-			rpn->xoff_char = RFCOMM_RPN_XOFF_CHAR;
+		xoff_char = rpn->xoff_char;
+		if (xoff_char != RFCOMM_RPN_XOFF_CHAR) {
+			BT_DBG("RPN XOFF char mismatch 0x%x", xoff_char);
+			xoff_char = RFCOMM_RPN_XOFF_CHAR;
 			rpn_mask ^= RFCOMM_RPN_PM_XOFF;
 		}
 	}
@@ -1280,11 +1297,11 @@
 
 	BT_DBG("dlci %d cr %d v24 0x%x", dlci, cr, msc->v24_sig);
 
-	if (!cr)
+	d = rfcomm_dlc_get(s, dlci);
+	if (!d)
 		return 0;
 
-	d = rfcomm_dlc_get(s, dlci);
-	if (d) {
+	if (cr) {
 		if (msc->v24_sig & RFCOMM_V24_FC && !d->credits)
 			set_bit(RFCOMM_TX_THROTTLED, &d->flags);
 		else
@@ -1296,7 +1313,11 @@
 		rfcomm_dlc_unlock(d);
 		
 		rfcomm_send_msc(s, 0, dlci, msc->v24_sig);
-	}
+
+		d->mscex |= RFCOMM_MSCEX_RX;
+	} else 
+		d->mscex |= RFCOMM_MSCEX_TX;
+
 	return 0;
 }
 
@@ -1520,7 +1541,8 @@
 			continue;
 		}
 
-		if (d->state == BT_CONNECTED || d->state == BT_DISCONN)
+		if ((d->state == BT_CONNECTED || d->state == BT_DISCONN) &&
+				d->mscex == RFCOMM_MSCEX_OK)
 			rfcomm_process_tx(d);
 	}
 }
@@ -1815,6 +1837,8 @@
 /* ---- Initialization ---- */
 int __init rfcomm_init(void)
 {
+	l2cap_load();
+
 	kernel_thread(rfcomm_run, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
 
 	rfcomm_init_sockets();

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)