|
From: Mattias A. <mat...@us...> - 2001-04-12 12:25:31
|
The following file was modified in linux/drivers/char/bluetooth:
Name Old version New version Comment
---- ----------- ----------- -------
rfcomm.c 1.98 1.99=20=20=20=20=20=20=20=20=20=20=20=20
The accompanying log:
* fixed credit based flow control when received piggybacked credits in=20
uih frame (thanks to David Libault)
* reset rfcomm session and unregister rfcomm even if disconnect fails=20
* fixed setting of control ch state before waking up disc wait queue
* fixed termination of rfcomm when baseband timed out
* fixed race in rfcomm_disconnect_ind, sometimes bt_hangupline flushed=20
outbuffer (containing l2ca_disconnect_rsp) before the scheduled data=20=
=20
was sent.=20
* added more debug
* cleanup & minor changes
The diff of the modified file(s):
--- rfcomm.c 2001/04/10 12:27:10 1.98
+++ rfcomm.c 2001/04/12 12:25:29 1.99
@@ -92,9 +92,9 @@
#endif
=20
#if PRINT_DATA_ENABLE
-#define PRINTPKT(str, data, len) print_data(str, data, len)
+#define RF_DATA(str, data, len) print_data(str, data, len)
#else
-#define PRINTPKT(str, data, len)
+#define RF_DATA(str, data, len)
#endif
=20
=20
@@ -554,6 +554,8 @@
static wait_queue_head_t rfcomm_disconnect_wq;
#endif /* LINUX_VERSION_CODE */
=20
+#else
+static int rfcomm_disconnect_wq;
#endif /* __KERNEL__ */
=20
void send_send_data(unsigned long ptr);
@@ -785,16 +787,33 @@
start_wq_timer(&rfcomm_timer, RFCOMM_CON_TIMEOUT,
&rfcomm_disconnect_wq);
=20
+#endif
/* FIXME -- check that we haven't already received=20
disconnect 'acknowledge' */
+
interruptible_sleep_on(&rfcomm_disconnect_wq);
=20
+ /* Check that rfcomm session really disconnected */
+ /* FIXME -- add timer obj with status in rfcomm obj */
+
+ /* check control channel */
+ if (rfcomm->dlci[0].state !=3D DISCONNECTED)
+ {
+ printk("Rfcomm disconnect failed, reset session\n");
+#ifdef __KERNEL__
+ bt_unregister_rfcomm(rfcomm->line);
+ bt_disconnect_cfm(CREATE_RFCOMM_ID(rfcomm->line, 0),=20
+ rfcomm->l2cap->c_result);
+#endif
+ rfcomm_reset_con(rfcomm->line);
+ }
+
/* Now rfcomm is disconnected, disconnect l2cap */
=20
l2ca_disconnect_req(rfcomm->l2cap);
=20
/* Now l2cap ch for RFCOMM is disconnected */
-#endif
+
}
else
D_WARN("rfcomm_disconnect_req : line not connected !\n");
@@ -967,7 +986,8 @@
{
=20=09=09=09
s32 j;
- DSYS(FNC"Setting RFCOMM frame size to %d\n", l2cap->remote_mtu-5);
+ DSYS(FNC"Setting RFCOMM frame size to %d\n",=20
+ l2cap->remote_mtu-5);
=20=09=09=09
for (j =3D 0; j < 62; j++) {
rfcomm->dlci[j].mtu =3D (l2cap->remote_mtu-5);
@@ -980,35 +1000,36 @@
=20
/* The lower protocol layer, L2CAP, indicates that the lower layer=20
connection is about to disconnect */
-
void=20
rfcomm_disconnect_ind(l2cap_con *l2cap)
{
-#define FNC "rfcomm_disconnect_ind: "
rfcomm_con *rfcomm;
=20
- D_CTRL(FNC"remote cid %d\n", l2cap->remote_cid);
+ D_CTRL(__FUNCTION__" remote cid %d\n", l2cap->remote_cid);
=20
rfcomm =3D ((rfcomm_con*) l2cap->upper_con);
=20
+ /* This l2cap connection is going down, remove all rfcomm cons=20
+ and notify upper tty */
=20
- /* FIXME -- disconnect all rfcomm cons on this l2cap con=20
- if any */
+ if (!l2cap->link_up)
+ {
+ DSYS("Baseband is down, reset this RFCOMM session\n");
+#ifdef __KERNEL__
+ bt_unregister_rfcomm(rfcomm->line);
+#endif
+ bt_disconnect_ind(CREATE_RFCOMM_ID(rfcomm->line, 0));
+ rfcomm_reset_con(rfcomm->line);
+ }
=20
+ /* always try to send back rsp (if link is down con is deleted) */
if (l2ca_disconnect_rsp(l2cap)) {
- D_ERR(FNC"l2ca_disconnect_rsp failed\n");
+ D_ERR(__FUNCTION__" l2ca_disconnect_rsp failed\n");
return;
}
-
-#ifdef __KERNEL__
- /* notify upper tty that this rfcomm connection is down */
- bt_hangupline(rfcomm->line);
-#else
- bt_disconnect_ind(CREATE_RFCOMM_ID(rfcomm->line, 0));
-#endif
-#undef FNC
}
=20
+
void=20
rfcomm_disconnect_cfm(l2cap_con *l2cap)
{
@@ -1023,6 +1044,8 @@
/* fixme -- should we indicate to bt interface when rfcomm is=20
down or when l2cap for rfcomm is down ? */
bt_disconnect_ind(CREATE_RFCOMM_ID(rfcomm->line, 0));
+
+ /* fixme -- add these glue layer functions in userstack */
#ifdef __KERNEL__
bt_unregister_rfcomm(rfcomm->line);
=20
@@ -1030,7 +1053,6 @@
bt_disconnect_cfm(CREATE_RFCOMM_ID(rfcomm->line, 0),=20
l2cap->c_result);
#endif
-=09
rfcomm_reset_con(rfcomm->line);
=20=09
#undef FNC
@@ -1051,7 +1073,7 @@
u32 uih_len;
u8 tmp_dlci;
=20
- PRINTPKT("rfcomm_receive_data:",data,len);
+ RF_DATA("rfcomm_receive_data:",data,len);
=20=09
D_REC(FNC"%d bytes, our cid is %d\n",len,=20
l2cap->remote_cid);
@@ -1172,14 +1194,13 @@
if (tmp_dlci =3D=3D 0) {
#ifdef __KERNEL__=09=09=09
release_wq_timer(&rfcomm_timer);
+#endif
+ printk("RFCOMM disconnected ctrl ch (local)\n");
+ rfcomm->dlci[0].state =3D DISCONNECTED;
+=09=09=09=09
/* this will take down l2cap aswell */
wake_up_interruptible(&rfcomm_disconnect_wq);
=20
-#else
- /* usermode stack */
- l2ca_disconnect_req(rfcomm->l2cap);
-#endif
-=20=20=20=20=20=20=20=20
} else {
s32 tmp;
rfcomm->dlci[tmp_dlci].state =3D DISCONNECTED;
@@ -1215,7 +1236,7 @@
rfcomm->dlci[0].state =3D DISCONNECTED;
/* FIXME:
Tell the tty that the link is down */
- printk("RFCOMM control ch disconnected\n");
+ printk("RFCOMM control ch disconnected (remotely)\n");
send_ua(rfcomm, tmp_dlci);
} else {
rfcomm->dlci[tmp_dlci].state =3D DISCONNECTED;
@@ -1258,14 +1279,15 @@
}
=20
if (GET_PF(short_pkt->h.control)) {
- printk(FNC" %d more credits on dlci:%d...\n",=20
+ D_REC(FNC" %d more credits on dlci:%d...\n",=20
*uih_data_start, tmp_dlci);
- if (crc_check(data, SHORT_CRC_CHECK,=20
- uih_data_start[1])) {
- break;
- }
- rfcomm->dlci[tmp_dlci].local_credits +=3D uih_data_start[0];
- break;
+
+ rfcomm->dlci[tmp_dlci].local_credits +=3D=20
+ uih_data_start[0];
+ uih_data_start++;
+
+ /* feed uih data to tty if any */
+
}
=20
if (crc_check(data, SHORT_CRC_CHECK,
@@ -1283,8 +1305,14 @@
if (rfcomm->credit_flow) {
rfcomm->dlci[tmp_dlci].remote_credits -=3D 1;
if (rfcomm->dlci[tmp_dlci].remote_credits <=3D 1) {
- rfcomm_send_credits(rfcomm, tmp_dlci, NBROFCREDITS -1);
- rfcomm->dlci[tmp_dlci].remote_credits +=3D NBROFCREDITS - 1;=20
+ /* FIXME -- possible race ? */
+=09=09=09=09=09
+ /* FIXME -- send credits piggybacked */
+
+ rfcomm_send_credits(rfcomm, tmp_dlci,=20
+ NBROFCREDITS -1);
+ rfcomm->dlci[tmp_dlci].remote_credits+=3D
+ NBROFCREDITS - 1;=20
}
}=09=09=09
bt_receive_top(con_id, uih_data_start, uih_len);
@@ -1318,10 +1346,11 @@
=20=09
if (dlci =3D=3D 0) {
D_ERR(FNC" Not allowed to send data on DLCI 0\n");
+ return -1;
}
=20=09
rfcomm =3D &rfcomm_con_list[line];
- PRINTPKT(FNC, data, count);
+ RF_DATA(FNC, data, count);
=20
if (rfcomm =3D=3D NULL) {
D_ERR(FNC" ERROR rfcomm_con =3D=3D NULL\n");
@@ -1331,11 +1360,11 @@
return -1;
} else if(rfcomm->dlci[0].state =3D=3D FLOW_STOPPED) {
DSYS(FNC"Flow stopped on all channels, returning zero\n");
- /* FIXME: We need to buffer the incomming data here... */
+ /* FIXME: We need to buffer the incoming data here... */
return 0;
} else if (rfcomm->dlci[dlci].state =3D=3D FLOW_STOPPED) {
DSYS(FNC"Flow stopped, returning zero\n");
- /* FIXME: We need to buffer the incomming data here... */
+ /* FIXME: We need to buffer the incoming data here... */
return 0;
}
/* Check whether there are any data channels connected */
@@ -1419,6 +1448,8 @@
#define FNC "process_mcc: "
mcc_short_frame *mcc_short_pkt;
=20=20=20=20=20
+ D_CTRL("process_mcc\n");
+
if (longpkt) {
mcc_short_pkt =3D (mcc_short_frame*)(((long_frame*)data)->data);
} else {
@@ -1480,7 +1511,7 @@
rfcomm->dlci[dlci].state =3D FLOW_STOPPED;
} else {
rfcomm->dlci[dlci].state =3D CONNECTED;
- D_CTRL(FNC"Flow on on dlci %d\n", dlci);
+ D_CTRL(FNC"Flow ON, dlci %d\n", dlci);
}
=20
rfcomm_msc_msg(rfcomm, v24_sigs, MCC_RSP, dlci);
@@ -1520,10 +1551,9 @@
memset(&rpn_val.pm, 0, 2);
}
}
-=20=20=20=20
-=09=09
break;
}
+
case RLS: /*Remote line status*/
{
u8 tmp_dlci;
@@ -1866,6 +1896,8 @@
short_frame *uih_pkt;
u32 rfcomm_frame_size;
=20=20=20
+ D_CTRL(__FUNCTION__" give %d credits to dlci %d\n", credits, dlci);
+
rfcomm_frame_size =3D (sizeof(short_frame) + 1 + FCS_SIZE);
tx_buf =3D subscribe_bt_buf(sizeof(rfcomm_tx_buf) + rfcomm_frame_size);
=20
@@ -2298,7 +2330,6 @@
return l2cap_send_data(tx_buf, rfcomm->l2cap);
}
=20
-
void
set_uih_hdr(short_frame *uih_pkt, u8 dlci, u32 len, u8 cr)
{
@@ -2327,7 +2358,7 @@
&& (rfcomm_con_list[i].dlci[0].state !=3D DISCONNECTED)) {
i++;
}
- D_CTRL("get_new_rfcomm_con: rfcomm_con -> tty%d\n",i);
+ D_CTRL("get_new_rfcomm_con: rfcomm_con -> ttyBT%d\n",i);
if (rfcomm_con_list[i].dlci[0].state !=3D DISCONNECTED) {
return NULL;
} else {
@@ -2378,7 +2409,7 @@
{
u8 fcs =3D 0xff;
=20
- PRINTPKT("crc_check:",data,length);
+ RF_DATA("crc_check:",data,length);
while (length--) {
fcs =3D crctable[fcs^*data++];
}
|