Skip to content

Commit

Permalink
Bluetooth: RFCOMM: Disconnect session after last dlc disconnection
Browse files Browse the repository at this point in the history
As per the spec the station which disconnects last dlc should initiate
session disconnection and then l2cap disconnection.

< ACL Data TX: Handle 256 flags 0x00 dlen 8
      Channel: 64 len 4 [PSM 3 mode 0] {chan 0}
      RFCOMM: Disconnect (DISC) (0x43)
         Address: 0x03 cr 1 dlci 0x00
         Control: 0x53 poll/final 1
         Length: 0
         FCS: 0xfd

> ACL Data RX: Handle 256 flags 0x02 dlen 8
      Channel: 64 len 4 [PSM 3 mode 0] {chan 0}
      RFCOMM: Unnumbered Ack (UA) (0x63)
         Address: 0x01 cr 0 dlci 0x00
         Control: 0x73 poll/final 1
         Length: 0
         FCS: 0xb6

Change-Id: I2d1d7d284995529d5d1522e0ca6082097db19bc2
Signed-off-by: Jaganath Kanakkassery <[email protected]>
  • Loading branch information
jkanakkx authored and Johan Hedberg committed Dec 16, 2016
1 parent bc8ec12 commit a95de43
Showing 1 changed file with 34 additions and 10 deletions.
44 changes: 34 additions & 10 deletions subsys/bluetooth/host/rfcomm.c
Original file line number Diff line number Diff line change
Expand Up @@ -804,23 +804,46 @@ static int rfcomm_dlc_start(struct bt_rfcomm_dlc *dlc)
return 0;
}

static void rfcomm_session_disconnect(struct bt_rfcomm_session *session)
{
if (session->dlcs) {
return;
}

session->state = BT_RFCOMM_STATE_DISCONNECTING;
rfcomm_send_disc(session, 0);
}

static void rfcomm_handle_ua(struct bt_rfcomm_session *session, uint8_t dlci)
{
struct bt_rfcomm_dlc *dlc, *tmp;
int err;

if (!dlci) {
if (session->state != BT_RFCOMM_STATE_CONNECTING) {
return;
}
session->state = BT_RFCOMM_STATE_CONNECTED;
for (dlc = session->dlcs; dlc; dlc = tmp) {
tmp = dlc->_next;
if (dlc->role == BT_RFCOMM_ROLE_INITIATOR &&
dlc->state == BT_RFCOMM_STATE_INIT) {
if (rfcomm_dlc_start(dlc) < 0) {
rfcomm_dlc_drop(dlc);
switch (session->state) {
case BT_RFCOMM_STATE_CONNECTING:
session->state = BT_RFCOMM_STATE_CONNECTED;
for (dlc = session->dlcs; dlc; dlc = tmp) {
tmp = dlc->_next;
if (dlc->role == BT_RFCOMM_ROLE_INITIATOR &&
dlc->state == BT_RFCOMM_STATE_INIT) {
if (rfcomm_dlc_start(dlc) < 0) {
rfcomm_dlc_drop(dlc);
}
}
}
/* Disconnect session if there is no dlcs left */
rfcomm_session_disconnect(session);
break;
case BT_RFCOMM_STATE_DISCONNECTING:
session->state = BT_RFCOMM_STATE_DISCONNECTED;
err = bt_l2cap_chan_disconnect(&session->br_chan.chan);
if (err < 0) {
session->state = BT_RFCOMM_STATE_IDLE;
}
break;
default:
break;
}
} else {
dlc = rfcomm_dlcs_lookup_dlci(session->dlcs, dlci);
Expand All @@ -834,6 +857,7 @@ static void rfcomm_handle_ua(struct bt_rfcomm_session *session, uint8_t dlci)
break;
case BT_RFCOMM_STATE_DISCONNECTING:
rfcomm_dlc_drop(dlc);
rfcomm_session_disconnect(session);
break;
default:
break;
Expand Down

0 comments on commit a95de43

Please sign in to comment.